diff -Nru thunderbird-91.7.0+build2/browser/components/extensions/parent/ext-chrome-settings-overrides.js thunderbird-91.8.1+build1/browser/components/extensions/parent/ext-chrome-settings-overrides.js --- thunderbird-91.7.0+build2/browser/components/extensions/parent/ext-chrome-settings-overrides.js 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/extensions/parent/ext-chrome-settings-overrides.js 2022-04-15 07:40:51.000000000 +0000 @@ -339,7 +339,9 @@ extension.startupReason ); } - if (disable && item?.enabled) { + // Ensure the item is disabled. If addSetting was called above, + // Item may be null, and enabled may be undefined. + if (disable && item?.enabled !== false) { item = await ExtensionSettingsStore.disable( extension.id, DEFAULT_SEARCH_STORE_TYPE, @@ -367,7 +369,10 @@ // This is a hack because we don't have the browser of // the actual install. This means the popup might show // in a different window. Will be addressed in a followup bug. - browser: windowTracker.topWindow.gBrowser.selectedBrowser, + // As well, we still notify if no topWindow exists to support + // testing from xpcshell. + browser: windowTracker.topWindow?.gBrowser.selectedBrowser, + id: extension.id, name: extension.name, icon: extension.iconURL, currentEngine: defaultEngine.name, @@ -476,7 +481,7 @@ Services.search.defaultEngine = Services.search.getEngineByName( engineName ); - } else { + } else if (extension.startupReason == "ADDON_ENABLE") { // This extension has precedence, but is not in control. Ask the user. await this.promptDefaultSearch(engineName); } diff -Nru thunderbird-91.7.0+build2/browser/components/extensions/test/browser/browser_ext_browserAction_popup_preload_smoketest.js thunderbird-91.8.1+build1/browser/components/extensions/test/browser/browser_ext_browserAction_popup_preload_smoketest.js --- thunderbird-91.7.0+build2/browser/components/extensions/test/browser/browser_ext_browserAction_popup_preload_smoketest.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/extensions/test/browser/browser_ext_browserAction_popup_preload_smoketest.js 2022-04-15 07:40:52.000000000 +0000 @@ -0,0 +1,198 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ +"use strict"; + +// This test does create and cancel the preloaded popup +// multiple times and in some cases it takes longer than +// the default timeouts allows. +requestLongerTimeout(4); + +const { AddonTestUtils } = ChromeUtils.import( + "resource://testing-common/AddonTestUtils.jsm" +); + +async function installTestAddon(addonId, unpacked = false) { + let xpi = AddonTestUtils.createTempWebExtensionFile({ + manifest: { + browser_specific_settings: { gecko: { id: addonId } }, + browser_action: { + default_popup: "popup.html", + }, + }, + files: { + "popup.html": ` + + + + + + + + + `, + "popup.css": `@import "imported.css";`, + "imported.css": ` + /* Increasing the imported.css file size to increase the + * chances to trigger the stylesheet preload issue that + * has been fixed by Bug 1735899 consistently and with + * a smaller number of preloaded popup cancelled. + * + * ${new Array(600000).fill("x").join("\n")} + */ + body { width: 300px; height: 300px; background: red; } + `, + }, + }); + + if (unpacked) { + // This temporary directory is going to be removed from the + // cleanup function, but also make it unique as we do for the + // other temporary files (e.g. like getTemporaryFile as defined + // in XPInstall.jsm). + const random = Math.round(Math.random() * 36 ** 3).toString(36); + const tmpDirName = `mochitest_unpacked_addons_${random}`; + let tmpExtPath = FileUtils.getDir("TmpD", [tmpDirName], true); + registerCleanupFunction(() => { + tmpExtPath.remove(true); + }); + + // Unpacking the xpi file into the tempoary directory. + const extDir = await AddonTestUtils.manuallyInstall( + xpi, + tmpExtPath, + null, + /* unpacked */ true + ); + + // Install temporarily as unpacked. + return AddonManager.installTemporaryAddon(extDir); + } + + // Install temporarily as packed. + return AddonManager.installTemporaryAddon(xpi); +} + +async function waitForExtensionAndBrowserAction(addonId) { + const { + Management: { + global: { browserActionFor }, + }, + } = ChromeUtils.import("resource://gre/modules/Extension.jsm"); + + // trigger a number of preloads + let extension; + let browserAction; + await TestUtils.waitForCondition(() => { + extension = WebExtensionPolicy.getByID(addonId)?.extension; + browserAction = extension && browserActionFor(extension); + return browserAction; + }, "got the extension and browserAction"); + + let widget = getBrowserActionWidget(extension).forWindow(window); + + return { extension, browserAction, widget }; +} + +async function testCancelPreloadedPopup({ browserAction, widget }) { + // Trigger the preloaded popup. + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mouseover", button: 0 }, + window + ); + await TestUtils.waitForCondition( + () => browserAction.pendingPopup, + "Wait for the preloaded popup" + ); + // Cancel the preloaded popup. + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mouseout", button: 0 }, + window + ); + EventUtils.synthesizeMouseAtCenter( + window.gURLBar.textbox, + { type: "mouseover" }, + window + ); + await TestUtils.waitForCondition( + () => !browserAction.pendingPopup, + "Wait for the preloaded popup to be cancelled" + ); +} + +async function testPopupLoadCompleted({ extension, browserAction, widget }) { + const promiseViewShowing = BrowserTestUtils.waitForEvent( + document, + "ViewShowing", + false, + ev => ev.target.id === browserAction.viewId + ); + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mousedown", button: 0 }, + window + ); + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mouseup", button: 0 }, + window + ); + + info("Await the browserAction popup to be shown"); + await promiseViewShowing; + + info("Await the browserAction popup to be fully loaded"); + const browser = await awaitExtensionPanel( + extension, + window, + /* awaitLoad */ true + ); + + await TestUtils.waitForCondition(async () => { + const docReadyState = await SpecialPowers.spawn(browser, [], () => { + return this.content.document.readyState; + }); + + return docReadyState === "complete"; + }, "Wait the popup document to get to readyState complete"); + + ok(true, "Popup document was fully loaded"); +} + +// This test is covering a scenario similar to the one fixed in Bug 1735899, +// and possibly some other similar ones that may slip through unnoticed. +add_task(async function testCancelPopupPreloadRaceOnUnpackedAddon() { + const ID = "preloaded-popup@test"; + const addon = await installTestAddon(ID, /* unpacked */ true); + const { + extension, + browserAction, + widget, + } = await waitForExtensionAndBrowserAction(ID); + info("Preload popup and cancel it multiple times"); + for (let i = 0; i < 200; i++) { + await testCancelPreloadedPopup({ browserAction, widget }); + } + await testPopupLoadCompleted({ extension, browserAction, widget }); + await addon.uninstall(); +}); + +// This test is covering a scenario similar to the one fixed in Bug 1735899, +// and possibly some other similar ones that may slip through unnoticed. +add_task(async function testCancelPopupPreloadRaceOnPackedAddon() { + const ID = "preloaded-popup@test"; + const addon = await installTestAddon(ID, /* unpacked */ false); + const { + extension, + browserAction, + widget, + } = await waitForExtensionAndBrowserAction(ID); + info("Preload popup and cancel it multiple times"); + for (let i = 0; i < 200; i++) { + await testCancelPreloadedPopup({ browserAction, widget }); + } + await testPopupLoadCompleted({ extension, browserAction, widget }); + await addon.uninstall(); +}); diff -Nru thunderbird-91.7.0+build2/browser/components/extensions/test/browser/browser.ini thunderbird-91.8.1+build1/browser/components/extensions/test/browser/browser.ini --- thunderbird-91.7.0+build2/browser/components/extensions/test/browser/browser.ini 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/extensions/test/browser/browser.ini 2022-04-15 07:40:51.000000000 +0000 @@ -69,6 +69,8 @@ [browser_ext_browserAction_popup_port.js] [browser_ext_browserAction_popup_preload.js] skip-if = (os == 'win' && !debug) || (verify && debug && (os == 'mac')) # bug 1352668 +[browser_ext_browserAction_popup_preload_smoketest.js] +skip-if = debug # Bug 1746047 [browser_ext_browserAction_popup_resize.js] [browser_ext_browserAction_popup_resize_bottom.js] skip-if = debug # Bug 1522164 diff -Nru thunderbird-91.7.0+build2/browser/components/extensions/test/xpcshell/test_ext_chrome_settings_overrides_update.js thunderbird-91.8.1+build1/browser/components/extensions/test/xpcshell/test_ext_chrome_settings_overrides_update.js --- thunderbird-91.7.0+build2/browser/components/extensions/test/xpcshell/test_ext_chrome_settings_overrides_update.js 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/extensions/test/xpcshell/test_ext_chrome_settings_overrides_update.js 2022-04-15 07:40:51.000000000 +0000 @@ -6,7 +6,9 @@ "resource://testing-common/AddonTestUtils.jsm" ); XPCOMUtils.defineLazyModuleGetters(this, { + AddonManager: "resource://gre/modules/AddonManager.jsm", HomePage: "resource:///modules/HomePage.jsm", + PromiseUtils: "resource://gre/modules/PromiseUtils.jsm", RemoteSettings: "resource://services-settings/remote-settings.js", sinon: "resource://testing-common/Sinon.jsm", }); @@ -24,6 +26,29 @@ // search service needs it. Services.prefs.clearUserPref("services.settings.default_bucket"); +// Similar to TestUtils.topicObserved, but returns a deferred promise that +// can be resolved +function topicObservable(topic, checkFn) { + let deferred = PromiseUtils.defer(); + function observer(subject, topic, data) { + try { + if (checkFn && !checkFn(subject, data)) { + return; + } + deferred.resolve([subject, data]); + } catch (ex) { + deferred.reject(ex); + } + } + deferred.promise.finally(() => { + Services.obs.removeObserver(observer, topic); + checkFn = null; + }); + Services.obs.addObserver(observer, topic); + + return deferred; +} + async function setupRemoteSettings() { const settings = await RemoteSettings("hijack-blocklists"); sinon.stub(settings, "get").returns([ @@ -50,7 +75,7 @@ /* This tests the scenario where the manifest key for homepage and/or * search_provider are removed between updates and therefore the * settings are expected to revert. It also tests that an extension - * can make a builtin extension the default extension without user + * can make a builtin extension the default search without user * interaction. */ const EXTENSION_ID = "test_overrides_update@tests.mozilla.org"; @@ -82,7 +107,20 @@ ok(defaultEngineName !== "DuckDuckGo", "Default engine is not DuckDuckGo."); let prefPromise = promisePrefChanged(HOMEPAGE_URI); - await extension.startup(); + + // When an addon is installed that overrides an app-provided engine (builtin) + // that is the default, we do not prompt for default. + let deferredPrompt = topicObservable( + "webextension-defaultsearch-prompt", + (subject, message) => { + if (subject.wrappedJSObject.id == extension.id) { + ok(false, "default override should not prompt"); + } + } + ); + + await Promise.race([extension.startup(), deferredPrompt.promise]); + deferredPrompt.resolve(); await AddonTestUtils.waitForSearchProviderStartup(extension); await prefPromise; @@ -197,7 +235,21 @@ }; let prefPromise = promisePrefChanged(HOMEPAGE_URI); - await extension.upgrade(extensionInfo); + + let deferredUpgradePrompt = topicObservable( + "webextension-defaultsearch-prompt", + (subject, message) => { + if (subject.wrappedJSObject.id == extension.id) { + ok(false, "should not prompt on update"); + } + } + ); + + await Promise.race([ + extension.upgrade(extensionInfo), + deferredUpgradePrompt.promise, + ]); + deferredUpgradePrompt.resolve(); await AddonTestUtils.waitForSearchProviderStartup(extension); await prefPromise; @@ -286,4 +338,131 @@ ); await extension.unload(); +}); + +add_task(async function test_default_search_prompts() { + /* This tests the scenario where an addon did not gain + * default search during install, and later upgrades. + * The addon should not gain default in updates. + * If the addon is disabled, it should prompt again when + * enabled. + */ + + const EXTENSION_ID = "test_default_update@tests.mozilla.org"; + + let extensionInfo = { + useAddonManager: "permanent", + manifest: { + version: "1.0", + applications: { + gecko: { + id: EXTENSION_ID, + }, + }, + chrome_settings_overrides: { + search_provider: { + name: "Example", + search_url: "https://example.com/?q={searchTerms}", + is_default: true, + }, + }, + }, + }; + + let extension = ExtensionTestUtils.loadExtension(extensionInfo); + + // Mock a response from the default search prompt where we + // say no to setting this as the default when installing. + let prompted = TestUtils.topicObserved( + "webextension-defaultsearch-prompt", + (subject, message) => { + if (subject.wrappedJSObject.id == extension.id) { + return subject.wrappedJSObject.respond(false); + } + } + ); + + let defaultEngineName = (await Services.search.getDefault()).name; + ok(defaultEngineName !== "Example", "Search is not Example."); + + await extension.startup(); + await prompted; + + equal( + extension.version, + "1.0", + "The installed addon has the expected version." + ); + equal( + (await Services.search.getDefault()).name, + defaultEngineName, + "Default engine is the default after startup." + ); + + extensionInfo.manifest = { + version: "2.0", + applications: { + gecko: { + id: EXTENSION_ID, + }, + }, + chrome_settings_overrides: { + search_provider: { + name: "Example", + search_url: "https://example.com/?q={searchTerms}", + is_default: true, + }, + }, + }; + + let deferredUpgradePrompt = topicObservable( + "webextension-defaultsearch-prompt", + (subject, message) => { + if (subject.wrappedJSObject.id == extension.id) { + ok(false, "should not prompt on update"); + } + } + ); + + await Promise.race([ + extension.upgrade(extensionInfo), + deferredUpgradePrompt.promise, + ]); + deferredUpgradePrompt.resolve(); + + await AddonTestUtils.waitForSearchProviderStartup(extension); + + equal( + extension.version, + "2.0", + "The updated addon has the expected version." + ); + // An upgraded extension does not become the default engine. + equal( + (await Services.search.getDefault()).name, + defaultEngineName, + "Default engine is still the default after startup." + ); + + let addon = await AddonManager.getAddonByID(EXTENSION_ID); + await addon.disable(); + + prompted = TestUtils.topicObserved( + "webextension-defaultsearch-prompt", + (subject, message) => { + if (subject.wrappedJSObject.id == extension.id) { + return subject.wrappedJSObject.respond(false); + } + } + ); + await Promise.all([addon.enable(), prompted]); + + // we still said no. + equal( + (await Services.search.getDefault()).name, + defaultEngineName, + "Default engine is the default after startup." + ); + + await extension.unload(); }); diff -Nru thunderbird-91.7.0+build2/browser/components/search/content/searchbar.js thunderbird-91.8.1+build1/browser/components/search/content/searchbar.js --- thunderbird-91.7.0+build2/browser/components/search/content/searchbar.js 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/search/content/searchbar.js 2022-04-15 07:40:52.000000000 +0000 @@ -807,10 +807,11 @@ }; this.textbox.onkeyup = event => { - if ( - event.keyCode === KeyEvent.DOM_VK_RETURN && - this._needBrowserFocusAtEnterKeyUp - ) { + // Pressing Enter key while pressing Meta key, and next, even when + // releasing Enter key before releasing Meta key, the keyup event is not + // fired. Therefore, if Enter keydown is detecting, continue the post + // processing for Enter key when any keyup event is detected. + if (this._needBrowserFocusAtEnterKeyUp) { this._needBrowserFocusAtEnterKeyUp = false; gBrowser.selectedBrowser.focus(); } diff -Nru thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-by/messages.json thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-by/messages.json --- thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-by/messages.json 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-by/messages.json 2022-04-15 07:40:52.000000000 +0000 @@ -0,0 +1,20 @@ +{ + "extensionName": { + "message": "Google" + }, + "extensionDescription": { + "message": "Google Search" + }, + "searchUrl": { + "message": "https://www.google.by/search" + }, + "searchForm": { + "message": "https://www.google.by/search?q={searchTerms}" + }, + "suggestUrl": { + "message": "https://www.google.by/complete/search?client=firefox&q={searchTerms}" + }, + "searchUrlGetParams": { + "message": "q={searchTerms}" + } +} diff -Nru thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-kz/messages.json thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-kz/messages.json --- thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-kz/messages.json 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-kz/messages.json 2022-04-15 07:40:52.000000000 +0000 @@ -0,0 +1,20 @@ +{ + "extensionName": { + "message": "Google" + }, + "extensionDescription": { + "message": "Google Search" + }, + "searchUrl": { + "message": "https://www.google.kz/search" + }, + "searchForm": { + "message": "https://www.google.kz/search?q={searchTerms}" + }, + "suggestUrl": { + "message": "https://www.google.kz/complete/search?client=firefox&q={searchTerms}" + }, + "searchUrlGetParams": { + "message": "q={searchTerms}" + } +} diff -Nru thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-ru/messages.json thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-ru/messages.json --- thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-ru/messages.json 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-ru/messages.json 2022-04-15 07:40:52.000000000 +0000 @@ -0,0 +1,20 @@ +{ + "extensionName": { + "message": "Google" + }, + "extensionDescription": { + "message": "Google Search" + }, + "searchUrl": { + "message": "https://www.google.ru/search" + }, + "searchForm": { + "message": "https://www.google.ru/search?q={searchTerms}" + }, + "suggestUrl": { + "message": "https://www.google.ru/complete/search?client=firefox&q={searchTerms}" + }, + "searchUrlGetParams": { + "message": "q={searchTerms}" + } +} diff -Nru thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-tr/messages.json thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-tr/messages.json --- thunderbird-91.7.0+build2/browser/components/search/extensions/google/_locales/region-tr/messages.json 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/search/extensions/google/_locales/region-tr/messages.json 2022-04-15 07:40:52.000000000 +0000 @@ -0,0 +1,20 @@ +{ + "extensionName": { + "message": "Google" + }, + "extensionDescription": { + "message": "Google Search" + }, + "searchUrl": { + "message": "https://www.google.com.tr/search" + }, + "searchForm": { + "message": "https://www.google.com.tr/search?q={searchTerms}" + }, + "suggestUrl": { + "message": "https://www.google.com.tr/complete/search?client=firefox&q={searchTerms}" + }, + "searchUrlGetParams": { + "message": "q={searchTerms}" + } +} diff -Nru thunderbird-91.7.0+build2/browser/components/search/extensions/google/manifest.json thunderbird-91.8.1+build1/browser/components/search/extensions/google/manifest.json --- thunderbird-91.7.0+build2/browser/components/search/extensions/google/manifest.json 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/search/extensions/google/manifest.json 2022-04-15 07:40:52.000000000 +0000 @@ -2,7 +2,7 @@ "name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__", "manifest_version": 2, - "version": "1.1", + "version": "1.2", "applications": { "gecko": { "id": "google@search.mozilla.org" diff -Nru thunderbird-91.7.0+build2/browser/components/search/test/browser/browser_searchbar_enter.js thunderbird-91.8.1+build1/browser/components/search/test/browser/browser_searchbar_enter.js --- thunderbird-91.7.0+build2/browser/components/search/test/browser/browser_searchbar_enter.js 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/search/test/browser/browser_searchbar_enter.js 2022-04-15 07:40:52.000000000 +0000 @@ -119,3 +119,38 @@ // Cleanup. await BrowserTestUtils.closeWindow(win); }); + +add_task(async function keyupEnterWhilePressingMeta() { + const win = await BrowserTestUtils.openNewBrowserWindow(); + const browser = win.gBrowser.selectedBrowser; + const searchBar = win.BrowserSearch.searchBar; + + info("Keydown Meta+Enter"); + searchBar.textbox.focus(); + searchBar.textbox.value = ""; + EventUtils.synthesizeKey( + "KEY_Enter", + { type: "keydown", metaKey: true }, + win + ); + + // Pressing Enter key while pressing Meta key, and next, even when releasing + // Enter key before releasing Meta key, the keyup event is not fired. + // Therefor, we fire Meta keyup event only. + info("Keyup Meta"); + EventUtils.synthesizeKey("KEY_Meta", { type: "keyup" }, win); + + await TestUtils.waitForCondition( + () => browser.ownerDocument.activeElement === browser, + "Wait for focus to be moved to the browser" + ); + info("The focus is moved to the browser"); + + info("Check whether we can input on the search bar"); + searchBar.textbox.focus(); + EventUtils.synthesizeKey("a", {}, win); + is(searchBar.textbox.value, "a", "Can input a char"); + + // Cleanup. + await BrowserTestUtils.closeWindow(win); +}); diff -Nru thunderbird-91.7.0+build2/browser/components/urlbar/tests/browser/browser_enter.js thunderbird-91.8.1+build1/browser/components/urlbar/tests/browser/browser_enter.js --- thunderbird-91.7.0+build2/browser/components/urlbar/tests/browser/browser_enter.js 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/urlbar/tests/browser/browser_enter.js 2022-04-15 07:40:52.000000000 +0000 @@ -303,3 +303,25 @@ // Cleanup. BrowserTestUtils.removeTab(tab); }); + +add_task(async function keyupEnterWhilePressingMeta() { + const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + + info("Keydown Meta+Enter"); + gURLBar.focus(); + gURLBar.value = ""; + EventUtils.synthesizeKey("KEY_Enter", { type: "keydown", metaKey: true }); + + // Pressing Enter key while pressing Meta key, and next, even when releasing + // Enter key before releasing Meta key, the keyup event is not fired. + // Therefor, we fire Meta keyup event only. + info("Keyup Meta"); + EventUtils.synthesizeKey("KEY_Meta", { type: "keyup" }); + + // Check whether we can input on URL bar. + EventUtils.synthesizeKey("a"); + is(gURLBar.value, "a", "Can input a char"); + + // Cleanup. + BrowserTestUtils.removeTab(tab); +}); diff -Nru thunderbird-91.7.0+build2/browser/components/urlbar/tests/unit/xpcshell.ini thunderbird-91.8.1+build1/browser/components/urlbar/tests/unit/xpcshell.ini --- thunderbird-91.7.0+build2/browser/components/urlbar/tests/unit/xpcshell.ini 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/urlbar/tests/unit/xpcshell.ini 2022-04-15 07:40:52.000000000 +0000 @@ -71,6 +71,7 @@ [test_tokenizer.js] [test_trimming.js] [test_unitConversion.js] +skip-if = true # Bug 1759318 [test_UrlbarController_integration.js] [test_UrlbarController_telemetry.js] [test_UrlbarController_unit.js] diff -Nru thunderbird-91.7.0+build2/browser/components/urlbar/UrlbarInput.jsm thunderbird-91.8.1+build1/browser/components/urlbar/UrlbarInput.jsm --- thunderbird-91.7.0+build2/browser/components/urlbar/UrlbarInput.jsm 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/components/urlbar/UrlbarInput.jsm 2022-04-15 07:40:52.000000000 +0000 @@ -3176,10 +3176,17 @@ } async _on_keyup(event) { - if ( - event.keyCode === KeyEvent.DOM_VK_RETURN && - this._keyDownEnterDeferred - ) { + if (event.keyCode === KeyEvent.DOM_VK_CONTROL) { + this._isKeyDownWithCtrl = false; + } + + this._toggleActionOverride(event); + + // Pressing Enter key while pressing Meta key, and next, even when releasing + // Enter key before releasing Meta key, the keyup event is not fired. + // Therefore, if Enter keydown is detecting, continue the post processing + // for Enter key when any keyup event is detected. + if (this._keyDownEnterDeferred) { if (this._keyDownEnterDeferred.loadedContent) { try { const loadingBrowser = await this._keyDownEnterDeferred.promise; @@ -3189,24 +3196,19 @@ // Make sure the domain name stays visible for spoof protection and usability. this.selectionStart = this.selectionEnd = 0; } - this._keyDownEnterDeferred = null; } catch (ex) { // Not all the Enter actions in the urlbar will cause a navigation, then it // is normal for this to be rejected. // If _keyDownEnterDeferred was rejected on keydown, we don't nullify it here // to ensure not overwriting the new value created by keydown. } - return; + } else { + // Discard the _keyDownEnterDeferred promise to receive any key inputs immediately. + this._keyDownEnterDeferred.resolve(); } - // Discard the _keyDownEnterDeferred promise to receive any key inputs immediately. - this._keyDownEnterDeferred.resolve(); this._keyDownEnterDeferred = null; - } else if (event.keyCode === KeyEvent.DOM_VK_CONTROL) { - this._isKeyDownWithCtrl = false; } - - this._toggleActionOverride(event); } _on_compositionstart(event) { diff -Nru thunderbird-91.7.0+build2/browser/config/version_display.txt thunderbird-91.8.1+build1/browser/config/version_display.txt --- thunderbird-91.7.0+build2/browser/config/version_display.txt 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/config/version_display.txt 2022-04-15 07:48:28.000000000 +0000 @@ -1 +1 @@ -91.7.0esr +91.8.0esr diff -Nru thunderbird-91.7.0+build2/browser/config/version.txt thunderbird-91.8.1+build1/browser/config/version.txt --- thunderbird-91.7.0+build2/browser/config/version.txt 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/browser/config/version.txt 2022-04-15 07:48:28.000000000 +0000 @@ -1 +1 @@ -91.7.0 +91.8.0 diff -Nru thunderbird-91.7.0+build2/BUILDID thunderbird-91.8.1+build1/BUILDID --- thunderbird-91.7.0+build2/BUILDID 2022-03-07 21:42:48.000000000 +0000 +++ thunderbird-91.8.1+build1/BUILDID 2022-04-15 08:10:45.000000000 +0000 @@ -1 +1 @@ -20220305171341 \ No newline at end of file +20220413002405 \ No newline at end of file diff -Nru thunderbird-91.7.0+build2/Cargo.lock thunderbird-91.8.1+build1/Cargo.lock --- thunderbird-91.7.0+build2/Cargo.lock 2022-03-07 21:32:50.000000000 +0000 +++ thunderbird-91.8.1+build1/Cargo.lock 2022-04-15 07:40:51.000000000 +0000 @@ -3888,6 +3888,7 @@ version = "0.2.0" dependencies = [ "libc", + "rustc_version", ] [[package]] @@ -4048,9 +4049,9 @@ [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", diff -Nru thunderbird-91.7.0+build2/comm/.gecko_rev.yml thunderbird-91.8.1+build1/comm/.gecko_rev.yml --- thunderbird-91.7.0+build2/comm/.gecko_rev.yml 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/.gecko_rev.yml 2022-04-15 07:49:20.000000000 +0000 @@ -1,8 +1,8 @@ --- GECKO_BASE_REPOSITORY: https://hg.mozilla.org/mozilla-unified GECKO_HEAD_REPOSITORY: https://hg.mozilla.org/releases/mozilla-esr91 -GECKO_HEAD_REF: FIREFOX_91_7_0esr_BUILD3 -GECKO_HEAD_REV: a9d3c0f4732a9a62428089fff64ae8ff3d608918 +GECKO_HEAD_REF: FIREFOX_91_8_0esr_BUILD1 +GECKO_HEAD_REV: 3b54d6b5407fca03efdb2e2f57a9838498e0d038 ### For comm-central # GECKO_BASE_REPOSITORY: https://hg.mozilla.org/mozilla-unified diff -Nru thunderbird-91.7.0+build2/comm/ldap/modules/LDAPClient.jsm thunderbird-91.8.1+build1/comm/ldap/modules/LDAPClient.jsm --- thunderbird-91.7.0+build2/comm/ldap/modules/LDAPClient.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/ldap/modules/LDAPClient.jsm 2022-04-15 07:49:20.000000000 +0000 @@ -9,6 +9,7 @@ var { AbandonRequest, BindRequest, + UnbindRequest, SearchRequest, LDAPResponse, } = ChromeUtils.import("resource:///modules/LDAPMessage.jsm"); @@ -110,6 +111,13 @@ } /** + * Send an unbind request to the server. + */ + unbind() { + return this._send(new UnbindRequest(), () => this._socket.close()); + } + + /** * Send a search request to the server. * @param {string} dn - The name to search. * @param {number} scope - The scope to search. diff -Nru thunderbird-91.7.0+build2/comm/ldap/modules/LDAPConnection.jsm thunderbird-91.8.1+build1/comm/ldap/modules/LDAPConnection.jsm --- thunderbird-91.7.0+build2/comm/ldap/modules/LDAPConnection.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/ldap/modules/LDAPConnection.jsm 2022-04-15 07:49:20.000000000 +0000 @@ -41,6 +41,11 @@ this.client.connect(); } + close() { + this.client.onError = () => {}; + this.client.unbind(); + } + get wrappedJSObject() { return this; } diff -Nru thunderbird-91.7.0+build2/comm/ldap/modules/LDAPMessage.jsm thunderbird-91.8.1+build1/comm/ldap/modules/LDAPMessage.jsm --- thunderbird-91.7.0+build2/comm/ldap/modules/LDAPMessage.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/ldap/modules/LDAPMessage.jsm 2022-04-15 07:49:20.000000000 +0000 @@ -5,6 +5,7 @@ const EXPORTED_SYMBOLS = [ "AbandonRequest", "BindRequest", + "UnbindRequest", "SearchRequest", "LDAPResponse", ]; @@ -124,6 +125,15 @@ } } +class UnbindRequest extends LDAPMessage { + static APPLICATION = 2; + + protocolOp = new asn1js.Primitive({ + // [APPLICATION 2] + idBlock: this._getApplicationId(UnbindRequest.APPLICATION), + }); +} + class SearchRequest extends LDAPMessage { static APPLICATION = 3; diff -Nru thunderbird-91.7.0+build2/comm/ldap/modules/LDAPOperation.jsm thunderbird-91.8.1+build1/comm/ldap/modules/LDAPOperation.jsm --- thunderbird-91.7.0+build2/comm/ldap/modules/LDAPOperation.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/ldap/modules/LDAPOperation.jsm 2022-04-15 07:49:20.000000000 +0000 @@ -92,6 +92,9 @@ }, }); } else if (res.constructor.name == "SearchResultDone") { + // NOTE: we create a new connection for every search, can be changed + // to reuse connections. + this._connection.wrappedJSObject.close(); this._messageId = null; this._listener.onLDAPMessage({ errorCode: res.result.resultCode, diff -Nru thunderbird-91.7.0+build2/comm/mail/app/settings/dumps/thunderbird/search-config.json thunderbird-91.8.1+build1/comm/mail/app/settings/dumps/thunderbird/search-config.json --- thunderbird-91.7.0+build2/comm/mail/app/settings/dumps/thunderbird/search-config.json 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/app/settings/dumps/thunderbird/search-config.json 2022-04-15 07:49:21.000000000 +0000 @@ -1 +1,2481 @@ -{"data":[{"appliesTo":[{"included":{"everywhere":true}}],"orderHint":500,"telemetryId":"ddg","webExtension":{"id":"ddg@search.mozilla.org","version":"1.0"},"id":"2c33bcaa-aae3-42e5-ad0d-915e2e822cc9","last_modified":1604535069307},{"appliesTo":[{"included":{"everywhere":true}},{"included":{"locales":{"matches":["af","an","ar","as","ast","az","be","bg","br","bs","crh","cy","da","de","dsb","el","eo","et","eu","fa","fi","fy-NL","ga-IE","gd","gl","gn","he","hr","hsb","hu","ia","id","is","it","ka","kab","kk","km","kn","lij","lo","lt","ltg","lv","mk","ml","mr","ms","my","nl","oc","or","pl","rm","ro","ru","si","sk","sl","sq","sr","sv-SE","ta","te","th","tl","tr","uk","ur","uz","vi","wo","zh-CN","zh-TW"]}},"webExtension":{"locales":["$USER_LOCALE"]}},{"included":{"locales":{"matches":["be"]}},"webExtension":{"locales":["be","be-tarask"]}},{"included":{"locales":{"matches":["bn","bn-BD","bn-IN"]}},"webExtension":{"locales":["bn"]}},{"included":{"locales":{"matches":["ca","ca-valencia"]}},"webExtension":{"locales":["ca"]}},{"included":{"locales":{"matches":["cak","es-AR","es-CL","es-ES","es-MX","trs"]}},"webExtension":{"locales":["es"]}},{"included":{"locales":{"matches":["cs"]}},"webExtension":{"locales":["cz"]}},{"included":{"locales":{"matches":["ff","fr","son"]}},"webExtension":{"locales":["fr"]}},{"included":{"locales":{"matches":["gu-IN"]}},"webExtension":{"locales":["gu"]}},{"included":{"locales":{"matches":["hi-IN"]}},"webExtension":{"locales":["hi"]}},{"included":{"locales":{"matches":["hy-AM"]}},"webExtension":{"locales":["hy"]}},{"included":{"locales":{"matches":["ja-JP-macos","ja"]}},"webExtension":{"locales":["ja"]}},{"included":{"locales":{"matches":["ko"]}},"webExtension":{"locales":["kr"]}},{"included":{"locales":{"matches":["mai"]}},"webExtension":{"locales":["hi"]}},{"included":{"locales":{"matches":["ml"]}},"webExtension":{"locales":["en","ml"]}},{"included":{"locales":{"matches":["nb-NO"]}},"webExtension":{"locales":["NO"]}},{"included":{"locales":{"matches":["ne-NP"]}},"webExtension":{"locales":["ne"]}},{"included":{"locales":{"matches":["nn-NO"]}},"webExtension":{"locales":["NN"]}},{"included":{"locales":{"matches":["pa-IN"]}},"webExtension":{"locales":["pa"]}},{"included":{"locales":{"matches":["pt-BR","pt-PT"]}},"webExtension":{"locales":["pt"]}}],"webExtension":{"id":"wikipedia@search.mozilla.org","version":"1.0"},"id":"8563efb6-e9f5-4f83-88b4-5124e5a51885","last_modified":1597452131957},{"appliesTo":[{"included":{"locales":{"matches":["sk"]}}}],"webExtension":{"id":"zoznam-sk@search.mozilla.org","version":"1.2"},"id":"208e5b83-ea31-4ad3-b5b1-8c46fdb646d2","last_modified":1597452131934},{"appliesTo":[{"included":{"locales":{"matches":["ja-JP-macos","ja"]}}}],"webExtension":{"id":"yahoo-jp-auctions@search.mozilla.org","version":"1.2"},"id":"3d048cc7-0b49-49f1-8275-25562f997cd4","last_modified":1597452131911},{"appliesTo":[{"included":{"locales":{"matches":["ja-JP-macos","ja"]}}}],"webExtension":{"id":"yahoo-jp@search.mozilla.org","version":"1.0"},"id":"4a3c25e9-32fc-43ba-9f64-04f44f23edf0","last_modified":1597452131889},{"appliesTo":[{"included":{"locales":{"matches":["pl"]}}}],"webExtension":{"id":"wolnelektury-pl@search.mozilla.org","version":"1.0"},"id":"cebf41a8-bb48-4f5a-b05a-404e57c4e019","last_modified":1597452131866},{"appliesTo":[{"included":{"locales":{"matches":["te"]}},"webExtension":{"locales":["te"]}},{"included":{"locales":{"matches":["oc"]}},"webExtension":{"locales":["oc"]}}],"webExtension":{"id":"wiktionary@search.mozilla.org","version":"1.0"},"id":"676fad59-3280-4e5d-a3ae-74c918f6b8d3","last_modified":1597452131842},{"appliesTo":[{"included":{"locales":{"matches":["hu"]}}}],"webExtension":{"id":"vatera@search.mozilla.org","version":"1.2"},"id":"ff997f3f-e41c-44e2-96b2-419a1ed7e7c4","last_modified":1597452131820},{"appliesTo":[{"included":{"locales":{"matches":["sv-SE"]}}}],"webExtension":{"id":"tyda-sv-SE@search.mozilla.org","version":"1.0"},"id":"f3930927-4422-4cc1-9576-b70a80e528b8","last_modified":1597452131797},{"appliesTo":[{"included":{"locales":{"matches":["ga-IE"]}}}],"webExtension":{"id":"tearma@search.mozilla.org","version":"1.0"},"id":"ada324f8-3081-4397-b78b-e03bd860375e","last_modified":1597452131747},{"appliesTo":[{"included":{"locales":{"matches":["ltg","lv"]}}}],"webExtension":{"id":"sslv@search.mozilla.org","version":"1.0"},"id":"3f907fb8-c074-444a-850f-b6ea3a651c56","last_modified":1597452131724},{"appliesTo":[{"included":{"locales":{"matches":["cs"]}}}],"webExtension":{"id":"seznam-cz@search.mozilla.org","version":"1.0"},"id":"38f61654-35a4-4c93-af84-7c215edaf434","last_modified":1597452131701},{"appliesTo":[{"included":{"locales":{"matches":["ltg","lv"]}}}],"webExtension":{"id":"salidzinilv@search.mozilla.org","version":"1.0"},"id":"6bec5c4a-0f12-4399-b4d5-2fe9d73c0e74","last_modified":1597452131679},{"appliesTo":[{"included":{"locales":{"matches":["zh-TW"]}}}],"webExtension":{"id":"readmoo@search.mozilla.org","version":"1.0"},"id":"4399d0ea-7540-43f6-adbd-4833b341ba9f","last_modified":1597452131655},{"appliesTo":[{"included":{"locales":{"matches":["ja-JP-macos","jp"]}}}],"webExtension":{"id":"rakuten@search.mozilla.org","version":"1.2"},"id":"fc2c153a-936c-4d7e-a72c-e0a7ce23b6d8","last_modified":1597452131632},{"appliesTo":[{"included":{"locales":{"matches":["nb-NO","nn-NO"]}}}],"webExtension":{"id":"qxl-NO@search.mozilla.org","version":"1.0"},"id":"dfc109bd-b4e5-4aa9-95a3-5cd81d67341d","last_modified":1597452131611},{"appliesTo":[{"included":{"locales":{"matches":["fr"]}}}],"webExtension":{"id":"qwant@search.mozilla.org","version":"1.0"},"id":"a0ce2b21-9204-486d-b0a1-07819e38b2e0","last_modified":1597452131588},{"appliesTo":[{"included":{"locales":{"matches":["pl"]}}}],"webExtension":{"id":"pwn-pl@search.mozilla.org","version":"1.0"},"id":"3f0b73cf-2645-427a-acbd-f9b9a7e86ca9","last_modified":1597452131564},{"appliesTo":[{"included":{"locales":{"matches":["sv-SE"]}}}],"webExtension":{"id":"prisjakt-sv-SE@search.mozilla.org","version":"1.0"},"id":"1a571c53-a05e-483f-ba76-944ce03e405c","last_modified":1597452131543},{"appliesTo":[{"included":{"locales":{"matches":["ru"]}}}],"webExtension":{"id":"priceru@search.mozilla.org","version":"1.0"},"id":"2ca250af-f2ac-4f63-af34-1b1b53fd3b92","last_modified":1597452131520},{"appliesTo":[{"included":{"locales":{"matches":["pt-PT"]}}}],"webExtension":{"id":"priberam@search.mozilla.org","version":"1.2"},"id":"44c5c666-422b-4fc2-b9e2-cddd0d3b7ccc","last_modified":1597452131497},{"appliesTo":[{"included":{"locales":{"matches":["sr"]}}}],"webExtension":{"id":"pogodak@search.mozilla.org","version":"1.0"},"id":"473fd16b-ed84-4ed1-822c-50ac5d9ee63b","last_modified":1597452131475},{"appliesTo":[{"included":{"locales":{"matches":["bg"]}}}],"webExtension":{"id":"pazaruvaj@search.mozilla.org","version":"1.0"},"id":"6752ecbe-99cc-4ce9-90db-31c8d9e7c506","last_modified":1597452131452},{"appliesTo":[{"included":{"locales":{"matches":["cy"]}}}],"webExtension":{"id":"palasprint@search.mozilla.org","version":"1.0"},"id":"1f5075fa-ed75-4561-919f-3fa6e1158bf7","last_modified":1597452131429},{"appliesTo":[{"included":{"locales":{"matches":["ru"]}}}],"webExtension":{"id":"ozonru@search.mozilla.org","version":"1.2"},"id":"954cc2fe-72f5-4360-b200-ab455c5ad920","last_modified":1597452131407},{"appliesTo":[{"included":{"locales":{"matches":["et"]}}}],"webExtension":{"id":"osta-ee@search.mozilla.org","version":"1.0"},"id":"e4e7b227-f6e6-49bf-840a-a7b7601e1a92","last_modified":1597452131384},{"appliesTo":[{"included":{"locales":{"matches":["ja-JP-macos","jp"]}}}],"webExtension":{"id":"oshiete-goo@search.mozilla.org","version":"1.0"},"id":"ba06b66e-b083-42f9-96ca-06beb7df003b","last_modified":1597452131360},{"appliesTo":[{"included":{"locales":{"matches":["bs"]}}}],"webExtension":{"id":"olx@search.mozilla.org","version":"1.0"},"id":"0a2b2d3b-18d7-425d-b852-319cafe49d22","last_modified":1597452131338},{"appliesTo":[{"included":{"locales":{"matches":["sl"]}}}],"webExtension":{"id":"odpiralni@search.mozilla.org","version":"1.0"},"id":"7e85688f-5f3e-4dce-a624-6a80ea792a39","last_modified":1597452131315},{"appliesTo":[{"included":{"locales":{"matches":["et"]}}}],"webExtension":{"id":"neti-ee@search.mozilla.org","version":"1.0"},"id":"c7cd702e-9049-4a75-823c-6ccd7ad2b86f","last_modified":1597452131292},{"appliesTo":[{"included":{"locales":{"matches":["ko"]}}}],"webExtension":{"id":"naver-kr@search.mozilla.org","version":"1.0"},"id":"af1943a3-75e1-4429-8a95-43675686786c","last_modified":1597452131271},{"appliesTo":[{"included":{"locales":{"matches":["sl"]}}}],"webExtension":{"id":"najdi-si@search.mozilla.org","version":"1.0"},"id":"fda60f56-ac34-410a-8e74-1b2ba0dbaeaa","last_modified":1597452131248},{"appliesTo":[{"included":{"locales":{"matches":["he"]}}}],"webExtension":{"id":"morfix-dic@search.mozilla.org","version":"1.1"},"id":"2950bf4a-450f-47cd-8988-1d9d73c10300","last_modified":1597452131225},{"appliesTo":[{"included":{"locales":{"matches":["pt-BR"]}}}],"webExtension":{"id":"mercadolivre@search.mozilla.org","version":"1.0"},"id":"393eed85-f54c-453c-9df3-d5351473a2d0","last_modified":1597452131204},{"appliesTo":[{"included":{"locales":{"matches":["es-AR"]}},"webExtension":{"locales":["ar"]}},{"included":{"locales":{"matches":["es-CL"]}},"webExtension":{"locales":["cl"]}},{"included":{"locales":{"matches":["es-MX"]}},"webExtension":{"locales":["mx"]}}],"webExtension":{"id":"mercadolibre@search.mozilla.org","version":"1.0"},"id":"58ccc938-9b28-43fa-99c8-8fb2afaf0531","last_modified":1597452131181},{"appliesTo":[{"included":{"locales":{"matches":["fy-NL"]}},"webExtension":{"locales":["fy-NL"]}},{"included":{"locales":{"matches":["nl"]}},"webExtension":{"locales":["nl"]}}],"webExtension":{"id":"marktplaats@search.mozilla.org","version":"1.0"},"id":"5e341152-6dc1-4357-80cb-8c2d615ec5dc","last_modified":1597452131158},{"appliesTo":[{"included":{"locales":{"matches":["cs"]}}}],"webExtension":{"id":"mapy-cz@search.mozilla.org","version":"1.0"},"id":"bcee8873-4644-44c1-babf-b35be366f4f7","last_modified":1597452131136},{"appliesTo":[{"included":{"locales":{"matches":["ru"]}}}],"webExtension":{"id":"mailru@search.mozilla.org","version":"1.0"},"id":"969a8778-1f6d-4af2-87cd-c08a9a4f80b8","last_modified":1597452131114},{"appliesTo":[{"included":{"locales":{"matches":["th"]}}}],"webExtension":{"id":"longdo@search.mozilla.org","version":"1.0"},"id":"c64fefb6-61b5-49fe-8148-1470fa586c21","last_modified":1597452131091},{"appliesTo":[{"included":{"locales":{"matches":["hy-AM"]}}}],"webExtension":{"id":"list-am@search.mozilla.org","version":"1.0"},"id":"2e099aaa-b949-4038-8595-69678b09c46d","last_modified":1597452131070},{"appliesTo":[{"included":{"locales":{"matches":["de","dsb","hsb","rm"]}}}],"webExtension":{"id":"leo_ende_de@search.mozilla.org","version":"1.0"},"id":"4db2ab80-c651-405b-88ba-1b30396a5d23","last_modified":1597452131047},{"appliesTo":[{"included":{"locales":{"matches":["kn"]}}}],"webExtension":{"id":"kannadastore@search.mozilla.org","version":"1.2"},"id":"8cb31936-c2da-47b6-8acc-15e2d48d2362","last_modified":1597452131024},{"appliesTo":[{"included":{"locales":{"matches":["uk"]}}}],"webExtension":{"id":"hotline-ua@search.mozilla.org","version":"1.0"},"id":"5b2895b4-afb4-452d-bc8f-4b3752448fba","last_modified":1597452131003},{"appliesTo":[{"included":{"locales":{"matches":["cs"]}}}],"webExtension":{"id":"heureka-cz@search.mozilla.org","version":"1.0"},"id":"dfc28b2a-40ac-4772-bca3-8b090ab8a05e","last_modified":1597452130980},{"appliesTo":[{"included":{"locales":{"matches":["nn-NO","nb-NO"]}}}],"webExtension":{"id":"gulesider-NO@search.mozilla.org","version":"1.0"},"id":"311b0b99-0619-446f-ad7c-695e531ec000","last_modified":1597452130957},{"appliesTo":[{"included":{"locales":{"matches":["br"]}}}],"webExtension":{"id":"freelang@search.mozilla.org","version":"1.0"},"id":"e72ce961-ea88-4296-ac41-745d75c14363","last_modified":1597452130936},{"appliesTo":[{"included":{"locales":{"matches":["kk"]}}}],"webExtension":{"id":"flip@search.mozilla.org","version":"1.0"},"id":"0b17f642-5519-4e5b-89bb-71e16e3e0763","last_modified":1597452130913},{"appliesTo":[{"included":{"locales":{"matches":["gd"]}}}],"webExtension":{"id":"faclair-beag@search.mozilla.org","version":"1.0"},"id":"2b046c0d-3cc6-4639-8454-2d2ea024705b","last_modified":1597452130891},{"appliesTo":[{"included":{"locales":{"matches":["hr"]}}}],"webExtension":{"id":"eudict@search.mozilla.org","version":"1.0"},"id":"1bf9f430-9b92-4c3b-a2c1-0a7edddc1f28","last_modified":1597452130869},{"appliesTo":[{"included":{"locales":{"matches":["et"]}}}],"webExtension":{"id":"eki-ee@search.mozilla.org","version":"1.0"},"id":"7c60a125-37c2-48f1-b541-86fe070b4388","last_modified":1597452130847},{"appliesTo":[{"included":{"locales":{"matches":["de"]}}}],"webExtension":{"id":"ecosia@search.mozilla.org","version":"1.0"},"id":"e7083870-11cf-4c2b-8843-67b3e098f474","last_modified":1597452130824},{"appliesTo":[{"included":{"locales":{"matches":["es-AR","es-CL","es-ES"]}}}],"webExtension":{"id":"drae@search.mozilla.org","version":"1.0"},"id":"fcf39b52-b59d-42a5-b1a8-4361159b428d","last_modified":1597452130803},{"appliesTo":[{"included":{"locales":{"matches":["ca","ca-valencia"]}}}],"webExtension":{"id":"diec2@search.mozilla.org","version":"1.2"},"id":"b88830cd-705d-492a-a28c-742abfa9334b","last_modified":1597452130780},{"appliesTo":[{"included":{"locales":{"matches":["ko"]}}}],"webExtension":{"id":"daum-kr@search.mozilla.org","version":"1.0"},"id":"2dc000ee-a78b-4e78-91af-ac76b79bac47","last_modified":1597452130756},{"appliesTo":[{"included":{"locales":{"matches":["vi"]}}}],"webExtension":{"id":"coccoc@search.mozilla.org","version":"1.0"},"id":"cd8d215b-6c81-439b-bc16-dab6bae8188b","last_modified":1597452130735},{"appliesTo":[{"included":{"locales":{"matches":["en-GB"]}}}],"webExtension":{"id":"chambers-en-GB@search.mozilla.org","version":"1.0"},"id":"7047c29e-7ad4-49db-adb9-6c135e6c59f8","last_modified":1597452130712},{"appliesTo":[{"included":{"locales":{"matches":["sl"]}}}],"webExtension":{"id":"ceneji@search.mozilla.org","version":"1.0"},"id":"c0fe16a1-6d66-48a2-bc54-ceb9a78754ce","last_modified":1597452130688},{"appliesTo":[{"included":{"locales":{"matches":["fy-NL"]}},"webExtension":{"locales":["fy-NL"]}},{"included":{"locales":{"matches":["nl"]}},"webExtension":{"locales":["nl"]}}],"webExtension":{"id":"bolcom@search.mozilla.org","version":"1.0"},"id":"adc06075-02c9-4d8d-88ab-bccd1b843184","last_modified":1597452130667},{"appliesTo":[{"included":{"locales":{"matches":["nb-NO","nn-NO"]}}}],"webExtension":{"id":"bok-NO@search.mozilla.org","version":"1.0"},"id":"dc33bc2b-758b-41fe-804c-e9894aea9cc1","last_modified":1597452130644},{"appliesTo":[{"included":{"locales":{"matches":["gd"]}}}],"webExtension":{"id":"bbc-alba@search.mozilla.org","version":"1.0"},"id":"614c27ea-1537-4db0-ac1d-b873732bde57","last_modified":1597452130621},{"appliesTo":[{"included":{"locales":{"matches":["sk"]}}}],"webExtension":{"id":"azet-sk@search.mozilla.org","version":"1.0"},"id":"17835df2-e2b8-4ca8-91bc-a45299bdcae5","last_modified":1597452130600},{"appliesTo":[{"included":{"locales":{"matches":["az"]}}}],"webExtension":{"id":"azerdict@search.mozilla.org","version":"1.0"},"id":"85d4f0c7-ace1-4e67-9e16-38db2aebf84b","last_modified":1597452130577},{"appliesTo":[{"included":{"locales":{"matches":["sk"]}}}],"webExtension":{"id":"atlas-sk@search.mozilla.org","version":"1.0"},"id":"bb87e317-4ba3-458e-9b64-d4459e61b001","last_modified":1597452130554},{"appliesTo":[{"included":{"locales":{"matches":["pl"]}}}],"webExtension":{"id":"allegro-pl@search.mozilla.org","version":"1.0"},"id":"9933195c-160e-41bb-984b-019137687d48","last_modified":1597452130533},{"appliesTo":[{"included":{"locales":{"matches":["sv-SE"]}}}],"webExtension":{"id":"allaannonser-sv-SE@search.mozilla.org","version":"1.2"},"id":"7011ae79-112a-494a-834b-857b66e444c0","last_modified":1597452130511},{"appliesTo":[{"default":"yes","included":{"locales":{"matches":["ru","tr","be","kk"],"startsWith":["en"]},"regions":["ru","tr","by","kz"]},"telemetryId":"yandex-en","webExtension":{"locales":["en"]}},{"included":{"locales":{"matches":["az"]}},"telemetryId":"yandex-az","webExtension":{"locales":["az"]}},{"included":{"locales":{"matches":["be"]}},"telemetryId":"yandex-by","webExtension":{"locales":["by"]}},{"included":{"locales":{"matches":["kk"]}},"telemetryId":"yandex-kk","webExtension":{"locales":["kk"]}},{"included":{"locales":{"matches":["ru"]}},"telemetryId":"yandex-ru","webExtension":{"locales":["ru"]}},{"included":{"locales":{"matches":["tr"]}},"telemetryId":"yandex-tr","webExtension":{"locales":["tr"]}}],"webExtension":{"id":"yandex@search.mozilla.org","version":"1.0"},"id":"cdfef3b9-59a5-4e58-998b-8f61e5f63279","last_modified":1597452130488},{"params":{"searchUrlGetParams":{"ix":"sunray","Go.x":"0","Go.y":"0","keywords":"{searchTerms}","pageletid":"headsearch","searchType":"","bestSaleNum":"0"}},"appliesTo":[{"included":{"locales":{"matches":["zh-CN"]}}}],"orderHint":500,"telemetryId":"amazondotcn","webExtension":{"id":"amazondotcn@search.mozilla.org","version":"1.0"},"id":"965270fc-b4ee-4dcc-bdcb-fed87fe563a9","last_modified":1597452130444},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"}]},"appliesTo":[{"included":{"locales":{"matches":["as","bn","bn-IN","kn","gu-IN","mai","ml","mr","or","pa-IN","ta","te","ur"]}},"telemetryId":"amazon-in","webExtension":{"locales":["in"]}},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"included":{"locales":{"matches":["br","ff","fr","son","wo"]}},"telemetryId":"amazon-france","webExtension":{"locales":["france"]}},{"included":{"locales":{"matches":["br","ff","fr","son","wo"]},"regions":["ca"]},"telemetryId":"amazon-ca","webExtension":{"locales":["ca"]}},{"included":{"locales":{"matches":["en-CA"]}},"telemetryId":"amazon-ca","webExtension":{"locales":["ca"]}},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"included":{"locales":{"matches":["ja-JP-macos","ja"]}},"telemetryId":"amazon-jp","webExtension":{"locales":["jp"]}},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"included":{"locales":{"matches":["it","lij"]}},"telemetryId":"amazon-it","webExtension":{"locales":["it"]}},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"included":{"locales":{"matches":["de","dsb","hsb"]}},"telemetryId":"amazon-de","webExtension":{"locales":["de"]}},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"included":{"locales":{"matches":["cy","da","el","en-GB","eu","ga-IE","gd","gl","hr","nb-NO","nn-NO","pt-PT","sq","sr"]}},"telemetryId":"amazon-en-GB","webExtension":{"locales":["en-GB"]}},{"included":{"locales":{"matches":["cy","da","el","en-GB","eu","ga-IE","gd","gl","hr","nb-NO","nn-NO","pt-PT","sq","sr"]},"regions":["au"]},"telemetryId":"amazon-au","webExtension":{"locales":["au"]}}],"orderHint":500,"webExtension":{"id":"amazon@search.mozilla.org","version":"1.1"},"id":"968c66a0-0d32-4bdb-a132-66d0e7dead54","last_modified":1597452130421},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"appliesTo":[{"included":{"regions":["default"]}},{"included":{"locales":{"matches":["ach","af","ar","az","bg","cak","en-US","eo","es-AR","fa","gn","hy-AM","ia","is","ka","km","lt","mk","ms","my","ro","si","th","tl","trs","uz"]}}},{"included":{"locales":{"matches":["ach","af","ar","az","bg","cak","en-US","eo","es-AR","fa","gn","hy-AM","ia","is","ka","km","lt","mk","ms","my","ro","si","th","tl","trs","uz"]},"regions":["au"]},"telemetryId":"amazon-au","webExtension":{"id":"amazon@search.mozilla.org","locales":["au"],"version":"1.1"}},{"included":{"locales":{"matches":["ach","af","ar","az","bg","cak","en-US","eo","es-AR","fa","gn","hy-AM","ia","is","ka","km","lt","mk","ms","my","ro","si","th","tl","trs","uz"]},"regions":["ca"]},"telemetryId":"amazon-ca","webExtension":{"id":"amazon@search.mozilla.org","locales":["ca"],"version":"1.1"}},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"included":{"locales":{"matches":["ach","af","ar","az","bg","cak","en-US","eo","es-AR","fa","gn","hy-AM","ia","is","ka","km","lt","mk","ms","my","ro","si","th","tl","trs","uz"]},"regions":["fr"]},"telemetryId":"amazon-france","webExtension":{"id":"amazon@search.mozilla.org","locales":["france"],"version":"1.1"}},{"params":{"searchUrlGetParams":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"ie","value":"{inputEncoding}"},{"name":"mode","value":"blended"},{"name":"sourceid","value":"Mozilla-search"}]},"included":{"locales":{"matches":["ach","af","ar","az","bg","cak","en-US","eo","es-AR","fa","gn","hy-AM","ia","is","ka","km","lt","mk","ms","my","ro","si","th","tl","trs","uz"]},"regions":["gb"]},"telemetryId":"amazon-en-GB","webExtension":{"id":"amazon@search.mozilla.org","locales":["en-GB"],"version":"1.1"}}],"orderHint":500,"telemetryId":"amazondotcom","webExtension":{"id":"amazondotcom@search.mozilla.org","version":"1.1"},"id":"5eb7e179-c11d-4029-99b7-bc7ea1467d46","last_modified":1597452130399},{"params":{"searchUrlGetParams":[{"name":"wd","value":"{searchTerms}"},{"name":"tn","value":"monline_7_dg"},{"name":"ie","value":"utf-8"}],"suggestUrlGetParams":[{"name":"wd","value":"{searchTerms}"},{"name":"tn","value":"monline_7_dg"},{"name":"ie","value":"utf-8"},{"name":"action","value":"opensearch"}]},"appliesTo":[{"included":{"locales":{"matches":["zh-CN"]}}},{"default":"yes","included":{"locales":{"matches":["zh-CN"]},"regions":["cn"]}}],"telemetryId":"baidu","webExtension":{"id":"baidu@search.mozilla.org","version":"1.0"},"id":"59f371ee-05cc-4c9e-8961-27fe1fa4cbc2","last_modified":1597452130376},{"params":{"searchUrlGetParams":[{"name":"q","value":"{searchTerms}"}]},"appliesTo":[{"included":{"locales":{"matches":["ach","af","an","ar","ast","az","ca","ca-valencia","cak","da","de","dsb","el","eo","es-CL","es-ES","es-MX","eu","fa","ff","fi","fr","fy-NL","gn","gu-IN","hi-IN","hr","hsb","ia","is","it","ja-JP-macos","ja","ka","kab","km","kn","lij","lo","lt","mai","mk","ml","ms","my","nb-NO","ne-NP","nl","nn-NO","oc","or","pa-IN","pt-BR","rm","ro","son","sq","sr","sv-SE","th","tl","trs","uk","ur","uz","wo","xh","zh-CN"],"startsWith":["bn","en"]}}},{"included":{"regions":["default"]}}],"webExtension":{"id":"bing@search.mozilla.org","version":"1.0"},"id":"d6b19d48-c263-49f9-9f5b-72fb5a3824bc","last_modified":1597452130353},{"params":{"searchUrlGetParams":[{"name":"q","value":"{searchTerms}"}]},"appliesTo":[{"default":"yes-if-no-other","included":{"everywhere":true}}],"orderHint":1000,"telemetryId":"google","webExtension":{"id":"google@search.mozilla.org","version":"1.0"},"id":"6158e467-c0d3-48e8-a5cf-a2102b7f9456","last_modified":1597452130330}]} \ No newline at end of file +{ + "data": [ + { + "appliesTo": [ + { + "included": { + "everywhere": true + } + } + ], + "orderHint": 500, + "telemetryId": "ddg", + "webExtension": { + "id": "ddg@search.mozilla.org", + "version": "1.0" + }, + "id": "2c33bcaa-aae3-42e5-ad0d-915e2e822cc9", + "last_modified": 1604535069307 + }, + { + "appliesTo": [ + { + "included": { + "everywhere": true + } + }, + { + "included": { + "locales": { + "matches": [ + "af", + "an", + "ar", + "as", + "ast", + "az", + "be", + "bg", + "br", + "bs", + "crh", + "cy", + "da", + "de", + "dsb", + "el", + "eo", + "et", + "eu", + "fa", + "fi", + "fy-NL", + "ga-IE", + "gd", + "gl", + "gn", + "he", + "hr", + "hsb", + "hu", + "ia", + "id", + "is", + "it", + "ka", + "kab", + "kk", + "km", + "kn", + "lij", + "lo", + "lt", + "ltg", + "lv", + "mk", + "ml", + "mr", + "ms", + "my", + "nl", + "oc", + "or", + "pl", + "rm", + "ro", + "ru", + "si", + "sk", + "sl", + "sq", + "sr", + "sv-SE", + "ta", + "te", + "th", + "tl", + "tr", + "uk", + "ur", + "uz", + "vi", + "wo", + "zh-CN", + "zh-TW" + ] + } + }, + "webExtension": { + "locales": [ + "$USER_LOCALE" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "be" + ] + } + }, + "webExtension": { + "locales": [ + "be", + "be-tarask" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "bn", + "bn-BD", + "bn-IN" + ] + } + }, + "webExtension": { + "locales": [ + "bn" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "ca", + "ca-valencia" + ] + } + }, + "webExtension": { + "locales": [ + "ca" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "cak", + "es-AR", + "es-CL", + "es-ES", + "es-MX", + "trs" + ] + } + }, + "webExtension": { + "locales": [ + "es" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "cs" + ] + } + }, + "webExtension": { + "locales": [ + "cz" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "ff", + "fr", + "son" + ] + } + }, + "webExtension": { + "locales": [ + "fr" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "gu-IN" + ] + } + }, + "webExtension": { + "locales": [ + "gu" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "hi-IN" + ] + } + }, + "webExtension": { + "locales": [ + "hi" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "hy-AM" + ] + } + }, + "webExtension": { + "locales": [ + "hy" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "ja-JP-macos", + "ja" + ] + } + }, + "webExtension": { + "locales": [ + "ja" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "ko" + ] + } + }, + "webExtension": { + "locales": [ + "kr" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "mai" + ] + } + }, + "webExtension": { + "locales": [ + "hi" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "ml" + ] + } + }, + "webExtension": { + "locales": [ + "en", + "ml" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "nb-NO" + ] + } + }, + "webExtension": { + "locales": [ + "NO" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "ne-NP" + ] + } + }, + "webExtension": { + "locales": [ + "ne" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "nn-NO" + ] + } + }, + "webExtension": { + "locales": [ + "NN" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "pa-IN" + ] + } + }, + "webExtension": { + "locales": [ + "pa" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "pt-BR", + "pt-PT" + ] + } + }, + "webExtension": { + "locales": [ + "pt" + ] + } + } + ], + "webExtension": { + "id": "wikipedia@search.mozilla.org", + "version": "1.0" + }, + "id": "8563efb6-e9f5-4f83-88b4-5124e5a51885", + "last_modified": 1597452131957 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sk" + ] + } + } + } + ], + "webExtension": { + "id": "zoznam-sk@search.mozilla.org", + "version": "1.2" + }, + "id": "208e5b83-ea31-4ad3-b5b1-8c46fdb646d2", + "last_modified": 1597452131934 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ja-JP-macos", + "ja" + ] + } + } + } + ], + "webExtension": { + "id": "yahoo-jp-auctions@search.mozilla.org", + "version": "1.2" + }, + "id": "3d048cc7-0b49-49f1-8275-25562f997cd4", + "last_modified": 1597452131911 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ja-JP-macos", + "ja" + ] + } + } + } + ], + "webExtension": { + "id": "yahoo-jp@search.mozilla.org", + "version": "1.0" + }, + "id": "4a3c25e9-32fc-43ba-9f64-04f44f23edf0", + "last_modified": 1597452131889 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "pl" + ] + } + } + } + ], + "webExtension": { + "id": "wolnelektury-pl@search.mozilla.org", + "version": "1.0" + }, + "id": "cebf41a8-bb48-4f5a-b05a-404e57c4e019", + "last_modified": 1597452131866 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "te" + ] + } + }, + "webExtension": { + "locales": [ + "te" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "oc" + ] + } + }, + "webExtension": { + "locales": [ + "oc" + ] + } + } + ], + "webExtension": { + "id": "wiktionary@search.mozilla.org", + "version": "1.0" + }, + "id": "676fad59-3280-4e5d-a3ae-74c918f6b8d3", + "last_modified": 1597452131842 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "hu" + ] + } + } + } + ], + "webExtension": { + "id": "vatera@search.mozilla.org", + "version": "1.2" + }, + "id": "ff997f3f-e41c-44e2-96b2-419a1ed7e7c4", + "last_modified": 1597452131820 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sv-SE" + ] + } + } + } + ], + "webExtension": { + "id": "tyda-sv-SE@search.mozilla.org", + "version": "1.0" + }, + "id": "f3930927-4422-4cc1-9576-b70a80e528b8", + "last_modified": 1597452131797 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ga-IE" + ] + } + } + } + ], + "webExtension": { + "id": "tearma@search.mozilla.org", + "version": "1.0" + }, + "id": "ada324f8-3081-4397-b78b-e03bd860375e", + "last_modified": 1597452131747 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ltg", + "lv" + ] + } + } + } + ], + "webExtension": { + "id": "sslv@search.mozilla.org", + "version": "1.0" + }, + "id": "3f907fb8-c074-444a-850f-b6ea3a651c56", + "last_modified": 1597452131724 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "cs" + ] + } + } + } + ], + "webExtension": { + "id": "seznam-cz@search.mozilla.org", + "version": "1.0" + }, + "id": "38f61654-35a4-4c93-af84-7c215edaf434", + "last_modified": 1597452131701 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ltg", + "lv" + ] + } + } + } + ], + "webExtension": { + "id": "salidzinilv@search.mozilla.org", + "version": "1.0" + }, + "id": "6bec5c4a-0f12-4399-b4d5-2fe9d73c0e74", + "last_modified": 1597452131679 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "zh-TW" + ] + } + } + } + ], + "webExtension": { + "id": "readmoo@search.mozilla.org", + "version": "1.0" + }, + "id": "4399d0ea-7540-43f6-adbd-4833b341ba9f", + "last_modified": 1597452131655 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ja-JP-macos", + "jp" + ] + } + } + } + ], + "webExtension": { + "id": "rakuten@search.mozilla.org", + "version": "1.2" + }, + "id": "fc2c153a-936c-4d7e-a72c-e0a7ce23b6d8", + "last_modified": 1597452131632 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "nb-NO", + "nn-NO" + ] + } + } + } + ], + "webExtension": { + "id": "qxl-NO@search.mozilla.org", + "version": "1.0" + }, + "id": "dfc109bd-b4e5-4aa9-95a3-5cd81d67341d", + "last_modified": 1597452131611 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "fr" + ] + } + } + } + ], + "webExtension": { + "id": "qwant@search.mozilla.org", + "version": "1.0" + }, + "id": "a0ce2b21-9204-486d-b0a1-07819e38b2e0", + "last_modified": 1597452131588 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "pl" + ] + } + } + } + ], + "webExtension": { + "id": "pwn-pl@search.mozilla.org", + "version": "1.0" + }, + "id": "3f0b73cf-2645-427a-acbd-f9b9a7e86ca9", + "last_modified": 1597452131564 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sv-SE" + ] + } + } + } + ], + "webExtension": { + "id": "prisjakt-sv-SE@search.mozilla.org", + "version": "1.0" + }, + "id": "1a571c53-a05e-483f-ba76-944ce03e405c", + "last_modified": 1597452131543 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ru" + ] + } + } + } + ], + "webExtension": { + "id": "priceru@search.mozilla.org", + "version": "1.0" + }, + "id": "2ca250af-f2ac-4f63-af34-1b1b53fd3b92", + "last_modified": 1597452131520 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "pt-PT" + ] + } + } + } + ], + "webExtension": { + "id": "priberam@search.mozilla.org", + "version": "1.2" + }, + "id": "44c5c666-422b-4fc2-b9e2-cddd0d3b7ccc", + "last_modified": 1597452131497 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sr" + ] + } + } + } + ], + "webExtension": { + "id": "pogodak@search.mozilla.org", + "version": "1.0" + }, + "id": "473fd16b-ed84-4ed1-822c-50ac5d9ee63b", + "last_modified": 1597452131475 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "bg" + ] + } + } + } + ], + "webExtension": { + "id": "pazaruvaj@search.mozilla.org", + "version": "1.0" + }, + "id": "6752ecbe-99cc-4ce9-90db-31c8d9e7c506", + "last_modified": 1597452131452 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "cy" + ] + } + } + } + ], + "webExtension": { + "id": "palasprint@search.mozilla.org", + "version": "1.0" + }, + "id": "1f5075fa-ed75-4561-919f-3fa6e1158bf7", + "last_modified": 1597452131429 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ru" + ] + } + } + } + ], + "webExtension": { + "id": "ozonru@search.mozilla.org", + "version": "1.2" + }, + "id": "954cc2fe-72f5-4360-b200-ab455c5ad920", + "last_modified": 1597452131407 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "et" + ] + } + } + } + ], + "webExtension": { + "id": "osta-ee@search.mozilla.org", + "version": "1.0" + }, + "id": "e4e7b227-f6e6-49bf-840a-a7b7601e1a92", + "last_modified": 1597452131384 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ja-JP-macos", + "jp" + ] + } + } + } + ], + "webExtension": { + "id": "oshiete-goo@search.mozilla.org", + "version": "1.0" + }, + "id": "ba06b66e-b083-42f9-96ca-06beb7df003b", + "last_modified": 1597452131360 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "bs" + ] + } + } + } + ], + "webExtension": { + "id": "olx@search.mozilla.org", + "version": "1.0" + }, + "id": "0a2b2d3b-18d7-425d-b852-319cafe49d22", + "last_modified": 1597452131338 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sl" + ] + } + } + } + ], + "webExtension": { + "id": "odpiralni@search.mozilla.org", + "version": "1.0" + }, + "id": "7e85688f-5f3e-4dce-a624-6a80ea792a39", + "last_modified": 1597452131315 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "et" + ] + } + } + } + ], + "webExtension": { + "id": "neti-ee@search.mozilla.org", + "version": "1.0" + }, + "id": "c7cd702e-9049-4a75-823c-6ccd7ad2b86f", + "last_modified": 1597452131292 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ko" + ] + } + } + } + ], + "webExtension": { + "id": "naver-kr@search.mozilla.org", + "version": "1.0" + }, + "id": "af1943a3-75e1-4429-8a95-43675686786c", + "last_modified": 1597452131271 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sl" + ] + } + } + } + ], + "webExtension": { + "id": "najdi-si@search.mozilla.org", + "version": "1.0" + }, + "id": "fda60f56-ac34-410a-8e74-1b2ba0dbaeaa", + "last_modified": 1597452131248 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "he" + ] + } + } + } + ], + "webExtension": { + "id": "morfix-dic@search.mozilla.org", + "version": "1.1" + }, + "id": "2950bf4a-450f-47cd-8988-1d9d73c10300", + "last_modified": 1597452131225 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "pt-BR" + ] + } + } + } + ], + "webExtension": { + "id": "mercadolivre@search.mozilla.org", + "version": "1.0" + }, + "id": "393eed85-f54c-453c-9df3-d5351473a2d0", + "last_modified": 1597452131204 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "es-AR" + ] + } + }, + "webExtension": { + "locales": [ + "ar" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "es-CL" + ] + } + }, + "webExtension": { + "locales": [ + "cl" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "es-MX" + ] + } + }, + "webExtension": { + "locales": [ + "mx" + ] + } + } + ], + "webExtension": { + "id": "mercadolibre@search.mozilla.org", + "version": "1.0" + }, + "id": "58ccc938-9b28-43fa-99c8-8fb2afaf0531", + "last_modified": 1597452131181 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "fy-NL" + ] + } + }, + "webExtension": { + "locales": [ + "fy-NL" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "nl" + ] + } + }, + "webExtension": { + "locales": [ + "nl" + ] + } + } + ], + "webExtension": { + "id": "marktplaats@search.mozilla.org", + "version": "1.0" + }, + "id": "5e341152-6dc1-4357-80cb-8c2d615ec5dc", + "last_modified": 1597452131158 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "cs" + ] + } + } + } + ], + "webExtension": { + "id": "mapy-cz@search.mozilla.org", + "version": "1.0" + }, + "id": "bcee8873-4644-44c1-babf-b35be366f4f7", + "last_modified": 1597452131136 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "th" + ] + } + } + } + ], + "webExtension": { + "id": "longdo@search.mozilla.org", + "version": "1.0" + }, + "id": "c64fefb6-61b5-49fe-8148-1470fa586c21", + "last_modified": 1597452131091 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "hy-AM" + ] + } + } + } + ], + "webExtension": { + "id": "list-am@search.mozilla.org", + "version": "1.0" + }, + "id": "2e099aaa-b949-4038-8595-69678b09c46d", + "last_modified": 1597452131070 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "de", + "dsb", + "hsb", + "rm" + ] + } + } + } + ], + "webExtension": { + "id": "leo_ende_de@search.mozilla.org", + "version": "1.0" + }, + "id": "4db2ab80-c651-405b-88ba-1b30396a5d23", + "last_modified": 1597452131047 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "kn" + ] + } + } + } + ], + "webExtension": { + "id": "kannadastore@search.mozilla.org", + "version": "1.2" + }, + "id": "8cb31936-c2da-47b6-8acc-15e2d48d2362", + "last_modified": 1597452131024 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "uk" + ] + } + } + } + ], + "webExtension": { + "id": "hotline-ua@search.mozilla.org", + "version": "1.0" + }, + "id": "5b2895b4-afb4-452d-bc8f-4b3752448fba", + "last_modified": 1597452131003 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "cs" + ] + } + } + } + ], + "webExtension": { + "id": "heureka-cz@search.mozilla.org", + "version": "1.0" + }, + "id": "dfc28b2a-40ac-4772-bca3-8b090ab8a05e", + "last_modified": 1597452130980 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "nn-NO", + "nb-NO" + ] + } + } + } + ], + "webExtension": { + "id": "gulesider-NO@search.mozilla.org", + "version": "1.0" + }, + "id": "311b0b99-0619-446f-ad7c-695e531ec000", + "last_modified": 1597452130957 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "br" + ] + } + } + } + ], + "webExtension": { + "id": "freelang@search.mozilla.org", + "version": "1.0" + }, + "id": "e72ce961-ea88-4296-ac41-745d75c14363", + "last_modified": 1597452130936 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "kk" + ] + } + } + } + ], + "webExtension": { + "id": "flip@search.mozilla.org", + "version": "1.0" + }, + "id": "0b17f642-5519-4e5b-89bb-71e16e3e0763", + "last_modified": 1597452130913 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "gd" + ] + } + } + } + ], + "webExtension": { + "id": "faclair-beag@search.mozilla.org", + "version": "1.0" + }, + "id": "2b046c0d-3cc6-4639-8454-2d2ea024705b", + "last_modified": 1597452130891 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "hr" + ] + } + } + } + ], + "webExtension": { + "id": "eudict@search.mozilla.org", + "version": "1.0" + }, + "id": "1bf9f430-9b92-4c3b-a2c1-0a7edddc1f28", + "last_modified": 1597452130869 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "et" + ] + } + } + } + ], + "webExtension": { + "id": "eki-ee@search.mozilla.org", + "version": "1.0" + }, + "id": "7c60a125-37c2-48f1-b541-86fe070b4388", + "last_modified": 1597452130847 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "de" + ] + } + } + } + ], + "webExtension": { + "id": "ecosia@search.mozilla.org", + "version": "1.0" + }, + "id": "e7083870-11cf-4c2b-8843-67b3e098f474", + "last_modified": 1597452130824 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "es-AR", + "es-CL", + "es-ES" + ] + } + } + } + ], + "webExtension": { + "id": "drae@search.mozilla.org", + "version": "1.0" + }, + "id": "fcf39b52-b59d-42a5-b1a8-4361159b428d", + "last_modified": 1597452130803 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ca", + "ca-valencia" + ] + } + } + } + ], + "webExtension": { + "id": "diec2@search.mozilla.org", + "version": "1.2" + }, + "id": "b88830cd-705d-492a-a28c-742abfa9334b", + "last_modified": 1597452130780 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ko" + ] + } + } + } + ], + "webExtension": { + "id": "daum-kr@search.mozilla.org", + "version": "1.0" + }, + "id": "2dc000ee-a78b-4e78-91af-ac76b79bac47", + "last_modified": 1597452130756 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "vi" + ] + } + } + } + ], + "webExtension": { + "id": "coccoc@search.mozilla.org", + "version": "1.0" + }, + "id": "cd8d215b-6c81-439b-bc16-dab6bae8188b", + "last_modified": 1597452130735 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "en-GB" + ] + } + } + } + ], + "webExtension": { + "id": "chambers-en-GB@search.mozilla.org", + "version": "1.0" + }, + "id": "7047c29e-7ad4-49db-adb9-6c135e6c59f8", + "last_modified": 1597452130712 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sl" + ] + } + } + } + ], + "webExtension": { + "id": "ceneji@search.mozilla.org", + "version": "1.0" + }, + "id": "c0fe16a1-6d66-48a2-bc54-ceb9a78754ce", + "last_modified": 1597452130688 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "fy-NL" + ] + } + }, + "webExtension": { + "locales": [ + "fy-NL" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "nl" + ] + } + }, + "webExtension": { + "locales": [ + "nl" + ] + } + } + ], + "webExtension": { + "id": "bolcom@search.mozilla.org", + "version": "1.0" + }, + "id": "adc06075-02c9-4d8d-88ab-bccd1b843184", + "last_modified": 1597452130667 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "nb-NO", + "nn-NO" + ] + } + } + } + ], + "webExtension": { + "id": "bok-NO@search.mozilla.org", + "version": "1.0" + }, + "id": "dc33bc2b-758b-41fe-804c-e9894aea9cc1", + "last_modified": 1597452130644 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "gd" + ] + } + } + } + ], + "webExtension": { + "id": "bbc-alba@search.mozilla.org", + "version": "1.0" + }, + "id": "614c27ea-1537-4db0-ac1d-b873732bde57", + "last_modified": 1597452130621 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sk" + ] + } + } + } + ], + "webExtension": { + "id": "azet-sk@search.mozilla.org", + "version": "1.0" + }, + "id": "17835df2-e2b8-4ca8-91bc-a45299bdcae5", + "last_modified": 1597452130600 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "az" + ] + } + } + } + ], + "webExtension": { + "id": "azerdict@search.mozilla.org", + "version": "1.0" + }, + "id": "85d4f0c7-ace1-4e67-9e16-38db2aebf84b", + "last_modified": 1597452130577 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sk" + ] + } + } + } + ], + "webExtension": { + "id": "atlas-sk@search.mozilla.org", + "version": "1.0" + }, + "id": "bb87e317-4ba3-458e-9b64-d4459e61b001", + "last_modified": 1597452130554 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "pl" + ] + } + } + } + ], + "webExtension": { + "id": "allegro-pl@search.mozilla.org", + "version": "1.0" + }, + "id": "9933195c-160e-41bb-984b-019137687d48", + "last_modified": 1597452130533 + }, + { + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "sv-SE" + ] + } + } + } + ], + "webExtension": { + "id": "allaannonser-sv-SE@search.mozilla.org", + "version": "1.2" + }, + "id": "7011ae79-112a-494a-834b-857b66e444c0", + "last_modified": 1597452130511 + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + } + ] + }, + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "as", + "bn", + "bn-IN", + "kn", + "gu-IN", + "mai", + "ml", + "mr", + "or", + "pa-IN", + "ta", + "te", + "ur" + ] + } + }, + "telemetryId": "amazon-in", + "webExtension": { + "locales": [ + "in" + ] + } + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "included": { + "locales": { + "matches": [ + "br", + "ff", + "fr", + "son", + "wo" + ] + } + }, + "telemetryId": "amazon-france", + "webExtension": { + "locales": [ + "france" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "br", + "ff", + "fr", + "son", + "wo" + ] + }, + "regions": [ + "ca" + ] + }, + "telemetryId": "amazon-ca", + "webExtension": { + "locales": [ + "ca" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "en-CA" + ] + } + }, + "telemetryId": "amazon-ca", + "webExtension": { + "locales": [ + "ca" + ] + } + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "included": { + "locales": { + "matches": [ + "ja-JP-macos", + "ja" + ] + } + }, + "telemetryId": "amazon-jp", + "webExtension": { + "locales": [ + "jp" + ] + } + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "included": { + "locales": { + "matches": [ + "it", + "lij" + ] + } + }, + "telemetryId": "amazon-it", + "webExtension": { + "locales": [ + "it" + ] + } + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "included": { + "locales": { + "matches": [ + "de", + "dsb", + "hsb" + ] + } + }, + "telemetryId": "amazon-de", + "webExtension": { + "locales": [ + "de" + ] + } + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "included": { + "locales": { + "matches": [ + "cy", + "da", + "el", + "en-GB", + "eu", + "ga-IE", + "gd", + "gl", + "hr", + "nb-NO", + "nn-NO", + "pt-PT", + "sq", + "sr" + ] + } + }, + "telemetryId": "amazon-en-GB", + "webExtension": { + "locales": [ + "en-GB" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "cy", + "da", + "el", + "en-GB", + "eu", + "ga-IE", + "gd", + "gl", + "hr", + "nb-NO", + "nn-NO", + "pt-PT", + "sq", + "sr" + ] + }, + "regions": [ + "au" + ] + }, + "telemetryId": "amazon-au", + "webExtension": { + "locales": [ + "au" + ] + } + } + ], + "orderHint": 500, + "webExtension": { + "id": "amazon@search.mozilla.org", + "version": "1.1" + }, + "id": "968c66a0-0d32-4bdb-a132-66d0e7dead54", + "last_modified": 1597452130421 + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "appliesTo": [ + { + "included": { + "regions": [ + "default" + ] + } + }, + { + "included": { + "locales": { + "matches": [ + "ach", + "af", + "ar", + "az", + "bg", + "cak", + "en-US", + "eo", + "es-AR", + "fa", + "gn", + "hy-AM", + "ia", + "is", + "ka", + "km", + "lt", + "mk", + "ms", + "my", + "ro", + "si", + "th", + "tl", + "trs", + "uz" + ] + } + } + }, + { + "included": { + "locales": { + "matches": [ + "ach", + "af", + "ar", + "az", + "bg", + "cak", + "en-US", + "eo", + "es-AR", + "fa", + "gn", + "hy-AM", + "ia", + "is", + "ka", + "km", + "lt", + "mk", + "ms", + "my", + "ro", + "si", + "th", + "tl", + "trs", + "uz" + ] + }, + "regions": [ + "au" + ] + }, + "telemetryId": "amazon-au", + "webExtension": { + "id": "amazon@search.mozilla.org", + "locales": [ + "au" + ], + "version": "1.1" + } + }, + { + "included": { + "locales": { + "matches": [ + "ach", + "af", + "ar", + "az", + "bg", + "cak", + "en-US", + "eo", + "es-AR", + "fa", + "gn", + "hy-AM", + "ia", + "is", + "ka", + "km", + "lt", + "mk", + "ms", + "my", + "ro", + "si", + "th", + "tl", + "trs", + "uz" + ] + }, + "regions": [ + "ca" + ] + }, + "telemetryId": "amazon-ca", + "webExtension": { + "id": "amazon@search.mozilla.org", + "locales": [ + "ca" + ], + "version": "1.1" + } + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "included": { + "locales": { + "matches": [ + "ach", + "af", + "ar", + "az", + "bg", + "cak", + "en-US", + "eo", + "es-AR", + "fa", + "gn", + "hy-AM", + "ia", + "is", + "ka", + "km", + "lt", + "mk", + "ms", + "my", + "ro", + "si", + "th", + "tl", + "trs", + "uz" + ] + }, + "regions": [ + "fr" + ] + }, + "telemetryId": "amazon-france", + "webExtension": { + "id": "amazon@search.mozilla.org", + "locales": [ + "france" + ], + "version": "1.1" + } + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "field-keywords", + "value": "{searchTerms}" + }, + { + "name": "ie", + "value": "{inputEncoding}" + }, + { + "name": "mode", + "value": "blended" + }, + { + "name": "sourceid", + "value": "Mozilla-search" + } + ] + }, + "included": { + "locales": { + "matches": [ + "ach", + "af", + "ar", + "az", + "bg", + "cak", + "en-US", + "eo", + "es-AR", + "fa", + "gn", + "hy-AM", + "ia", + "is", + "ka", + "km", + "lt", + "mk", + "ms", + "my", + "ro", + "si", + "th", + "tl", + "trs", + "uz" + ] + }, + "regions": [ + "gb" + ] + }, + "telemetryId": "amazon-en-GB", + "webExtension": { + "id": "amazon@search.mozilla.org", + "locales": [ + "en-GB" + ], + "version": "1.1" + } + } + ], + "orderHint": 500, + "telemetryId": "amazondotcom", + "webExtension": { + "id": "amazondotcom@search.mozilla.org", + "version": "1.1" + }, + "id": "5eb7e179-c11d-4029-99b7-bc7ea1467d46", + "last_modified": 1597452130399 + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "wd", + "value": "{searchTerms}" + }, + { + "name": "tn", + "value": "monline_7_dg" + }, + { + "name": "ie", + "value": "utf-8" + } + ], + "suggestUrlGetParams": [ + { + "name": "wd", + "value": "{searchTerms}" + }, + { + "name": "tn", + "value": "monline_7_dg" + }, + { + "name": "ie", + "value": "utf-8" + }, + { + "name": "action", + "value": "opensearch" + } + ] + }, + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "zh-CN" + ] + } + } + }, + { + "default": "yes", + "included": { + "locales": { + "matches": [ + "zh-CN" + ] + }, + "regions": [ + "cn" + ] + } + } + ], + "telemetryId": "baidu", + "webExtension": { + "id": "baidu@search.mozilla.org", + "version": "1.0" + }, + "id": "59f371ee-05cc-4c9e-8961-27fe1fa4cbc2", + "last_modified": 1597452130376 + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "q", + "value": "{searchTerms}" + } + ] + }, + "appliesTo": [ + { + "included": { + "locales": { + "matches": [ + "ach", + "af", + "an", + "ar", + "ast", + "az", + "ca", + "ca-valencia", + "cak", + "da", + "de", + "dsb", + "el", + "eo", + "es-CL", + "es-ES", + "es-MX", + "eu", + "fa", + "ff", + "fi", + "fr", + "fy-NL", + "gn", + "gu-IN", + "hi-IN", + "hr", + "hsb", + "ia", + "is", + "it", + "ja-JP-macos", + "ja", + "ka", + "kab", + "km", + "kn", + "lij", + "lo", + "lt", + "mai", + "mk", + "ml", + "ms", + "my", + "nb-NO", + "ne-NP", + "nl", + "nn-NO", + "oc", + "or", + "pa-IN", + "pt-BR", + "rm", + "ro", + "son", + "sq", + "sr", + "sv-SE", + "th", + "tl", + "trs", + "uk", + "ur", + "uz", + "wo", + "xh", + "zh-CN" + ], + "startsWith": [ + "bn", + "en" + ] + } + } + }, + { + "included": { + "regions": [ + "default" + ] + } + } + ], + "webExtension": { + "id": "bing@search.mozilla.org", + "version": "1.0" + }, + "id": "d6b19d48-c263-49f9-9f5b-72fb5a3824bc", + "last_modified": 1597452130353 + }, + { + "params": { + "searchUrlGetParams": [ + { + "name": "q", + "value": "{searchTerms}" + } + ] + }, + "appliesTo": [ + { + "default": "yes-if-no-other", + "included": { + "everywhere": true + } + } + ], + "orderHint": 1000, + "telemetryId": "google", + "webExtension": { + "id": "google@search.mozilla.org", + "version": "1.0" + }, + "id": "6158e467-c0d3-48e8-a5cf-a2102b7f9456", + "last_modified": 1597452130330 + } + ] +} diff -Nru thunderbird-91.7.0+build2/comm/mail/base/content/mailCommands.js thunderbird-91.8.1+build1/comm/mail/base/content/mailCommands.js --- thunderbird-91.7.0+build2/comm/mail/base/content/mailCommands.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/base/content/mailCommands.js 2022-04-15 07:49:21.000000000 +0000 @@ -237,7 +237,8 @@ Ci.nsIMsgCompType.Reply, Ci.nsIMsgCompType.ReplyAll, Ci.nsIMsgCompType.ReplyToSender, - Ci.nsIMsgCompType.ReplyToGroup, + // Author's address doesn't matter for followup to a newsgroup. + // Ci.nsIMsgCompType.ReplyToGroup, Ci.nsIMsgCompType.ReplyToSenderAndGroup, Ci.nsIMsgCompType.ReplyWithTemplate, Ci.nsIMsgCompType.ReplyToList, diff -Nru thunderbird-91.7.0+build2/comm/mail/base/content/msgMail3PaneWindow.js thunderbird-91.8.1+build1/comm/mail/base/content/msgMail3PaneWindow.js --- thunderbird-91.7.0+build2/comm/mail/base/content/msgMail3PaneWindow.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/base/content/msgMail3PaneWindow.js 2022-04-15 07:49:21.000000000 +0000 @@ -1211,6 +1211,10 @@ Services.tm.dispatchToMainThread(loadExtraTabs); SessionStoreManager._restored = true; Services.obs.notifyObservers(window, "mail-tabs-session-restored"); + // Notify observer to resolve the browserStartupPromise, which is used for the + // delayed background startup of WebExtensions. + Services.obs.notifyObservers(window, "extensions-late-startup"); + return !!state; } diff -Nru thunderbird-91.7.0+build2/comm/mail/base/test/unit/test_oauth_migration.js thunderbird-91.8.1+build1/comm/mail/base/test/unit/test_oauth_migration.js --- thunderbird-91.7.0+build2/comm/mail/base/test/unit/test_oauth_migration.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/base/test/unit/test_oauth_migration.js 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,301 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test migrating Yahoo/AOL users to OAuth2, since "normal password" is going away + * on October 20, 2020. + */ + +var { MailMigrator } = ChromeUtils.import( + "resource:///modules/MailMigrator.jsm" +); +var { localAccountUtils } = ChromeUtils.import( + "resource://testing-common/mailnews/LocalAccountUtils.jsm" +); +var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +var gAccountList = [ + // POP Yahoo account + Yahoo Server. + { + type: "pop3", + port: 1234, + user: "pop3user", + password: "pop3password", + hostname: "pop3.mail.yahoo.com", + socketType: Ci.nsMsgSocketType.plain, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + smtpServers: [ + { + port: 3456, + user: "imapout", + password: "imapoutpassword", + isDefault: true, + hostname: "smtp.mail.yahoo.com", + socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + }, + ], + }, + // IMAP Yahoo account + Google Server. + { + type: "imap", + port: 2345, + user: "imapuser", + password: "imappassword", + hostname: "imap.mail.yahoo.com", + socketType: Ci.nsMsgSocketType.trySTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + smtpServers: [ + { + port: 3456, + user: "imapout", + password: "imapoutpassword", + isDefault: false, + hostname: "smtp.gmail.com", + socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, + }, + ], + }, + // IMAP Google account + Yahoo Server. + { + type: "imap", + port: 2345, + user: "imap2user", + password: "imap2password", + hostname: "imap.gmail.com", + socketType: Ci.nsMsgSocketType.trySTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + smtpServers: [ + { + port: 3456, + user: "imapout", + password: "imapoutpassword", + isDefault: false, + hostname: "smtp.mail.yahoo.com", + socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, + }, + ], + }, + // IMAP Invalid account + Invalid Server. + { + type: "imap", + port: 2345, + user: "imap2user", + password: "imap2password", + hostname: "imap.mail.foo.invalid", + socketType: Ci.nsMsgSocketType.trySTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + smtpServers: [ + { + port: 3456, + user: "imapout", + password: "imapoutpassword", + isDefault: false, + hostname: "smtp.mail.foo.invalid", + socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, + }, + ], + }, + // AOL IMAP account. + { + type: "imap", + port: 993, + user: "aolimap", + password: "imap2password", + hostname: "imap.aol.com", + socketType: Ci.nsMsgSocketType.SSL, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + smtpServers: [ + { + port: 465, + user: "imapout2", + password: "imapoutpassword2", + isDefault: false, + hostname: "smtp.aol.com", + socketType: Ci.nsMsgSocketType.SSL, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + }, + ], + }, + // AOL POP3 account. + { + type: "pop3", + port: 995, + user: "aolpop3", + password: "abc", + hostname: "pop.aol.com", + socketType: Ci.nsMsgSocketType.SSL, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + smtpServers: [ + { + port: 465, + user: "popout", + password: "aaa", + isDefault: false, + hostname: "smtp.aol.com", + socketType: Ci.nsMsgSocketType.SSL, + authMethod: Ci.nsMsgAuthMethod.passwordCleartext, + }, + ], + }, + // Google POP3 account. + { + type: "pop3", + port: 995, + user: "gmailpop3", + password: "abc", + hostname: "pop.gmail.com", + socketType: Ci.nsMsgSocketType.trySTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, + smtpServers: [ + { + port: 465, + user: "gmailpopout", + password: "aaa", + isDefault: true, + hostname: "smtp.gmail.com", + socketType: Ci.nsMsgAuthMethod.alwaysSTARTTLS, + authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, + }, + ], + }, +]; + +// An array of the incoming servers created from the setup_accounts() method. +var gIncomingServers = []; + +// An array of the outgoing servers created from the setup_accounts() method. +var gOutgoingServers = []; + +// An array of the accounts created from the setup_accounts() method. +var gAccounts = []; + +/** + * Set up accounts based on the given data. + */ +function setup_accounts() { + for (let details of gAccountList) { + let server = localAccountUtils.create_incoming_server( + details.type, + details.port, + details.user, + details.password, + details.hostname + ); + server.socketType = details.socketType; + server.authMethod = details.authMethod; + + // Add the newly created server to the array for testing. + gIncomingServers.push(server); + + let account = MailServices.accounts.FindAccountForServer(server); + for (let smtpDetails of details.smtpServers) { + let outgoing = localAccountUtils.create_outgoing_server( + smtpDetails.port, + smtpDetails.user, + smtpDetails.password, + smtpDetails.hostname + ); + outgoing.socketType = smtpDetails.socketType; + outgoing.authMethod = smtpDetails.authMethod; + localAccountUtils.associate_servers( + account, + outgoing, + smtpDetails.isDefault + ); + + // Add the newly created server to the array for testing. + gOutgoingServers.push(outgoing); + + // Add the newly created account to the array for cleanup. + gAccounts.push(account); + } + } +} + +function test_oauth_migration() { + setup_accounts(); + + for (let server of gIncomingServers) { + // Confirm all the incoming servers are not using OAuth2 after the setup. + Assert.notEqual( + server.authMethod, + Ci.nsMsgAuthMethod.OAuth2, + "Incoming server should not use OAuth2" + ); + } + + for (let server of gOutgoingServers) { + // Confirm all the outgoing servers are not using OAuth2 after the setup. + Assert.notEqual( + server.authMethod, + Ci.nsMsgAuthMethod.OAuth2, + "Outgoing server should not use OAuth2" + ); + } + + // Run the migration. + Services.prefs.setIntPref("mail.ui-rdf.version", 21); + MailMigrator._migrateUI(); + + for (let server of gIncomingServers) { + // Confirm only the correct incoming servers are using OAuth2 after migration. + if ( + !server.hostName.endsWith("mail.yahoo.com") && + !server.hostName.endsWith("aol.com") && + !server.hostName.endsWith("gmail.com") + ) { + Assert.notEqual( + server.authMethod, + Ci.nsMsgAuthMethod.OAuth2, + `Incoming server ${server.hostName} should not use OAuth2 after migration` + ); + continue; + } + + Assert.equal( + server.authMethod, + Ci.nsMsgAuthMethod.OAuth2, + `Incoming server ${server.hostName} should use OAuth2 after migration` + ); + } + + for (let server of gOutgoingServers) { + // Confirm only the correct outgoing servers are using OAuth2 after migration. + if ( + !server.hostname.endsWith("mail.yahoo.com") && + !server.hostname.endsWith("aol.com") && + !server.hostname.endsWith("gmail.com") + ) { + Assert.notEqual( + server.authMethod, + Ci.nsMsgAuthMethod.OAuth2, + `Outgoing server ${server.hostname} should not use OAuth2 after migration` + ); + continue; + } + + Assert.equal( + server.authMethod, + Ci.nsMsgAuthMethod.OAuth2, + `Outgoing server ${server.hostname} should use OAuth2 after migration` + ); + } + + // Remove our test accounts and servers to leave the profile clean. + for (let account of gAccounts) { + MailServices.accounts.removeAccount(account); + } + + for (let server of gOutgoingServers) { + MailServices.smtp.deleteServer(server); + } +} + +function run_test() { + test_oauth_migration(); +} diff -Nru thunderbird-91.7.0+build2/comm/mail/base/test/unit/test_yahoo_oauth_migration.js thunderbird-91.8.1+build1/comm/mail/base/test/unit/test_yahoo_oauth_migration.js --- thunderbird-91.7.0+build2/comm/mail/base/test/unit/test_yahoo_oauth_migration.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/base/test/unit/test_yahoo_oauth_migration.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,278 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Test migrating Yahoo/AOL users to OAuth2, since "normal password" is going away - * on October 20, 2020. - */ - -var { MailMigrator } = ChromeUtils.import( - "resource:///modules/MailMigrator.jsm" -); -var { localAccountUtils } = ChromeUtils.import( - "resource://testing-common/mailnews/LocalAccountUtils.jsm" -); -var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); - -var gAccountList = [ - // POP Yahoo account + Yahoo Server. - { - type: "pop3", - port: 1234, - user: "pop3user", - password: "pop3password", - hostname: "pop3.mail.yahoo.com", - socketType: Ci.nsMsgSocketType.plain, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - smtpServers: [ - { - port: 3456, - user: "imapout", - password: "imapoutpassword", - isDefault: true, - hostname: "smtp.mail.yahoo.com", - socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - }, - ], - }, - // IMAP Yahoo account + Google Server. - { - type: "imap", - port: 2345, - user: "imapuser", - password: "imappassword", - hostname: "imap.mail.yahoo.com", - socketType: Ci.nsMsgSocketType.trySTARTTLS, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - smtpServers: [ - { - port: 3456, - user: "imapout", - password: "imapoutpassword", - isDefault: false, - hostname: "smtp.mail.google.com", - socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, - authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, - }, - ], - }, - // IMAP Google account + Yahoo Server. - { - type: "imap", - port: 2345, - user: "imap2user", - password: "imap2password", - hostname: "imap.mail.google.com", - socketType: Ci.nsMsgSocketType.trySTARTTLS, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - smtpServers: [ - { - port: 3456, - user: "imapout", - password: "imapoutpassword", - isDefault: false, - hostname: "smtp.mail.yahoo.com", - socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, - authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, - }, - ], - }, - // IMAP Invalid account + Invalid Server. - { - type: "imap", - port: 2345, - user: "imap2user", - password: "imap2password", - hostname: "imap.mail.foo.invalid", - socketType: Ci.nsMsgSocketType.trySTARTTLS, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - smtpServers: [ - { - port: 3456, - user: "imapout", - password: "imapoutpassword", - isDefault: false, - hostname: "smtp.mail.foo.invalid", - socketType: Ci.nsMsgSocketType.alwaysSTARTTLS, - authMethod: Ci.nsMsgAuthMethod.passwordEncrypted, - }, - ], - }, - // AOL IMAP account. - { - type: "imap", - port: 993, - user: "aolimap", - password: "imap2password", - hostname: "imap.aol.com", - socketType: Ci.nsMsgSocketType.SSL, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - smtpServers: [ - { - port: 465, - user: "imapout2", - password: "imapoutpassword2", - isDefault: false, - hostname: "smtp.aol.com", - socketType: Ci.nsMsgSocketType.SSL, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - }, - ], - }, - // AOL POP3 account. - { - type: "pop3", - port: 995, - user: "aolpop3", - password: "abc", - hostname: "pop.aol.com", - socketType: Ci.nsMsgSocketType.SSL, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - smtpServers: [ - { - port: 465, - user: "popout", - password: "aaa", - isDefault: false, - hostname: "smtp.aol.com", - socketType: Ci.nsMsgSocketType.SSL, - authMethod: Ci.nsMsgAuthMethod.passwordCleartext, - }, - ], - }, -]; - -// An array of the incoming servers created from the setup_accounts() method. -var gIncomingServers = []; - -// An array of the outgoing servers created from the setup_accounts() method. -var gOutgoingServers = []; - -// An array of the accounts created from the setup_accounts() method. -var gAccounts = []; - -/** - * Set up accounts based on the given data. - */ -function setup_accounts() { - for (let details of gAccountList) { - let server = localAccountUtils.create_incoming_server( - details.type, - details.port, - details.user, - details.password, - details.hostname - ); - server.socketType = details.socketType; - server.authMethod = details.authMethod; - - // Add the newly created server to the array for testing. - gIncomingServers.push(server); - - let account = MailServices.accounts.FindAccountForServer(server); - for (let smtpDetails of details.smtpServers) { - let outgoing = localAccountUtils.create_outgoing_server( - smtpDetails.port, - smtpDetails.user, - smtpDetails.password, - smtpDetails.hostname - ); - outgoing.socketType = smtpDetails.socketType; - outgoing.authMethod = smtpDetails.authMethod; - localAccountUtils.associate_servers( - account, - outgoing, - smtpDetails.isDefault - ); - - // Add the newly created server to the array for testing. - gOutgoingServers.push(outgoing); - - // Add the newly created account to the array for cleanup. - gAccounts.push(account); - } - } -} - -function test_yahoo_oauth_migration() { - setup_accounts(); - - for (let server of gIncomingServers) { - // Confirm all the incoming servers are not using OAuth2 after the setup. - Assert.notEqual( - server.authMethod, - Ci.nsMsgAuthMethod.OAuth2, - "Incoming server doesn't use OAuth2" - ); - } - - for (let server of gOutgoingServers) { - // Confirm all the outgoing servers are not using OAuth2 after the setup. - Assert.notEqual( - server.authMethod, - Ci.nsMsgAuthMethod.OAuth2, - "Outgoing server doesn't use OAuth2" - ); - } - - // Run the migration. - Services.prefs.setIntPref("mail.ui-rdf.version", 21); - MailMigrator._migrateUI(); - - for (let server of gIncomingServers) { - // Confirm only the correct incoming servers are using OAuth2 after migration. - if ( - !server.hostName.endsWith("mail.yahoo.com") && - !server.hostName.endsWith("aol.com") - ) { - Assert.notEqual( - server.authMethod, - Ci.nsMsgAuthMethod.OAuth2, - `Incoming server ${server.hostName} doesn't use OAuth2 after migration` - ); - continue; - } - - Assert.equal( - server.authMethod, - Ci.nsMsgAuthMethod.OAuth2, - `Incoming server ${server.hostName} should use OAuth2 after migration` - ); - } - - for (let server of gOutgoingServers) { - // Confirm only the correct outgoing servers are using OAuth2 after migration. - if ( - !server.hostname.endsWith("mail.yahoo.com") && - !server.hostname.endsWith("aol.com") - ) { - Assert.notEqual( - server.authMethod, - Ci.nsMsgAuthMethod.OAuth2, - `Outgoing server ${server.hostname} doesn't use OAuth2 after migration` - ); - continue; - } - - Assert.equal( - server.authMethod, - Ci.nsMsgAuthMethod.OAuth2, - `Outgoing server ${server.hostname} should use OAuth2 after migration` - ); - } - - // Remove our test accounts and servers to leave the profile clean. - for (let account of gAccounts) { - MailServices.accounts.removeAccount(account); - } - - for (let server of gOutgoingServers) { - MailServices.smtp.deleteServer(server); - } -} - -function run_test() { - test_yahoo_oauth_migration(); -} diff -Nru thunderbird-91.7.0+build2/comm/mail/base/test/unit/xpcshell.ini thunderbird-91.8.1+build1/comm/mail/base/test/unit/xpcshell.ini --- thunderbird-91.7.0+build2/comm/mail/base/test/unit/xpcshell.ini 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/base/test/unit/xpcshell.ini 2022-04-15 07:49:21.000000000 +0000 @@ -18,7 +18,7 @@ run-sequentially = Avoid bustage. [test_windows_font_migration.js] skip-if = os != "win" -[test_yahoo_oauth_migration.js] +[test_oauth_migration.js] [test_mailGlue_distribution.js] [include:xpcshell_maildir.ini] diff -Nru thunderbird-91.7.0+build2/comm/mail/components/compose/content/MsgComposeCommands.js thunderbird-91.8.1+build1/comm/mail/components/compose/content/MsgComposeCommands.js --- thunderbird-91.7.0+build2/comm/mail/components/compose/content/MsgComposeCommands.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/components/compose/content/MsgComposeCommands.js 2022-04-15 07:49:21.000000000 +0000 @@ -6724,7 +6724,7 @@ document.l10n.setAttributes( document.getElementById("attachmentBucketCount"), - "attachment-bucket-count", + "attachment-bucket-count-value", { count } ); diff -Nru thunderbird-91.7.0+build2/comm/mail/components/MessengerContentHandler.jsm thunderbird-91.8.1+build1/comm/mail/components/MessengerContentHandler.jsm --- thunderbird-91.7.0+build2/comm/mail/components/MessengerContentHandler.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/components/MessengerContentHandler.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -296,6 +296,8 @@ // The URI might be passed as the argument to the file parameter uri = cmdLine.handleFlagWithParam("file", false); + // macOS passes `-url mid:` into the command line, drop the -url flag. + cmdLine.handleFlag("url", false); var count = cmdLine.length; if (count) { @@ -346,6 +348,8 @@ } } if (uri) { + // Check for protocols first then look at the file ending. + // Protocols are able to contain file endings like '.ics'. if (/^https?:/i.test(uri)) { Cc["@mozilla.org/newsblog-feed-downloader;1"] .getService(Ci.nsINewsBlogFeedDownloader) @@ -448,6 +452,31 @@ Services.prompt.alert(null, title, message); } + } else if (/^webcals?:\/\//i.test(uri)) { + Services.ww.openWindow( + null, + "chrome://calendar/content/calendar-creation.xhtml", + "_blank", + "chrome,titlebar,modal,centerscreen", + Services.io.newURI(uri) + ); + } else if (/^mid:/i.test(uri)) { + let { MailUtils } = ChromeUtils.import( + "resource:///modules/MailUtils.jsm" + ); + MailUtils.openMessageByMessageId(uri.slice(4)); + } else if (uri.toLowerCase().endsWith(".ics")) { + // An .ics calendar file! Open the ics file dialog. + let file = cmdLine.resolveFile(uri); + if (file.exists() && file.fileSize > 0) { + Services.ww.openWindow( + null, + "chrome://calendar/content/calendar-ics-file-dialog.xhtml", + "_blank", + "chrome,titlebar,modal,centerscreen", + file + ); + } } else if (uri.toLowerCase().endsWith(".vcf")) { // A VCard! Be smart and open the "add contact" dialog. let file = cmdLine.resolveFile(uri); @@ -489,31 +518,6 @@ } ); } - } else if (uri.toLowerCase().endsWith(".ics")) { - // An .ics calendar file! Open the ics file dialog. - let file = cmdLine.resolveFile(uri); - if (file.exists() && file.fileSize > 0) { - Services.ww.openWindow( - null, - "chrome://calendar/content/calendar-ics-file-dialog.xhtml", - "_blank", - "chrome,titlebar,modal,centerscreen", - file - ); - } - } else if (/^webcals?:\/\//i.test(uri)) { - Services.ww.openWindow( - null, - "chrome://calendar/content/calendar-creation.xhtml", - "_blank", - "chrome,titlebar,modal,centerscreen", - Services.io.newURI(uri) - ); - } else if (/^mid:/i.test(uri)) { - let { MailUtils } = ChromeUtils.import( - "resource:///modules/MailUtils.jsm" - ); - MailUtils.openMessageByMessageId(uri.slice(4)); } else { // This must be a regular filename. Use it to create a new message with attachment. let msgParams = Cc[ diff -Nru thunderbird-91.7.0+build2/comm/mail/config/version_display.txt thunderbird-91.8.1+build1/comm/mail/config/version_display.txt --- thunderbird-91.7.0+build2/comm/mail/config/version_display.txt 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/config/version_display.txt 2022-04-15 07:49:21.000000000 +0000 @@ -1 +1 @@ -91.7.0 +91.8.1 diff -Nru thunderbird-91.7.0+build2/comm/mail/config/version.txt thunderbird-91.8.1+build1/comm/mail/config/version.txt --- thunderbird-91.7.0+build2/comm/mail/config/version.txt 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/config/version.txt 2022-04-15 07:49:21.000000000 +0000 @@ -1 +1 @@ -91.7.0 +91.8.1 diff -Nru thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/modules/keyRing.jsm thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/modules/keyRing.jsm --- thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/modules/keyRing.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/modules/keyRing.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -694,8 +694,8 @@ minimizeKey, limitedUids, importSecret, - passCB, allowPermissiveFallbackWithPrompt, + passCB, acceptance ) ); diff -Nru thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/modules/RNP.jsm thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/modules/RNP.jsm --- thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/modules/RNP.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/modules/RNP.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -644,14 +644,53 @@ return true; }, + /* + // We don't need these functions currently, but it's helpful + // information that I'd like to keep around as documentation. + + isUInt64WithinBounds(val) { + // JS integers are limited to 53 bits precision. + // Numbers smaller than 2^53 -1 are safe to use. + // (For comparison, that's 8192 TB or 8388608 GB). + const num53BitsMinus1 = ctypes.UInt64("0x1fffffffffffff"); + return ctypes.UInt64.compare(val, num53BitsMinus1) < 0; + }, + + isUInt64Max(val) { + // 2^64-1, 18446744073709551615 + const max = ctypes.UInt64("0xffffffffffffffff"); + return ctypes.UInt64.compare(val, max) == 0; + }, + */ + isBadKey(handle) { - let validTill = new ctypes.uint32_t(); - if (RNPLib.rnp_key_valid_till(handle, validTill.address())) { - throw new Error("rnp_key_valid_till failed"); + let validTill64 = new ctypes.uint64_t(); + if (RNPLib.rnp_key_valid_till64(handle, validTill64.address())) { + throw new Error("rnp_key_valid_till64 failed"); + } + + // For the purpose of this function, we define bad as: there isn't + // any valid self-signature on the key, and thus the key should + // be completely avoided. + // In this scenario, zero is returned. In other words, + // if a non-zero value is returned, we know the key isn't completely + // bad according to our definition. + + // ctypes.uint64_t().value is of type ctypes.UInt64 + + if (ctypes.UInt64.compare(validTill64.value, ctypes.UInt64("0")) > 0) { + return false; } - // A bad key is invalid for any time - return !validTill.value; + // If zero was returned, it could potentially have been revoked. + // If it was revoked, we don't treat is as generally bad, + // to allow importing it and to consume the revocation information. + // If the key was not revoked, then treat it as a bad key. + let key_revoked = new ctypes.bool(); + if (RNPLib.rnp_key_is_revoked(handle, key_revoked.address())) { + throw new Error("rnp_key_is_revoked failed"); + } + return !key_revoked.value; }, isPrimaryUid(uid_handle) { @@ -726,6 +765,10 @@ RNPLib.ffi, "0x" + keyId ); + if (handle.isNull()) { + return null; + } + let mainKeyObj = {}; this.getKeyInfoFromHandle( RNPLib.ffi, @@ -1925,20 +1968,17 @@ // We allow importing, if any of the following is true // - it contains a secret key // - it contains at least one user ID + // - it is an update for an existing key (possibly new validity/revocation) if (k.userIds.length == 0 && !k.secretAvailable) { - continue; - // TODO: bug 1634524 requests that we import keys without user - // ID, if we already have this key. - // It hasn't been tested yet how well this works. - /* - let existingKey = await this.getKeyHandleByIdentifier(RNPLib.ffi, "0x" + k.fpr); + let existingKey = await this.getKeyHandleByIdentifier( + RNPLib.ffi, + "0x" + k.fpr + ); if (existingKey.isNull()) { continue; - } else { - RNPLib.rnp_key_handle_destroy(existingKey); } - */ + RNPLib.rnp_key_handle_destroy(existingKey); } let impKey = await this.getKeyHandleByIdentifier(tempFFI, fprStr); @@ -2178,7 +2218,18 @@ if (RNPLib.rnp_key_allows_usage(key, usage, allowed.address())) { throw new Error("rnp_key_allows_usage failed"); } - return allowed.value; + if (!allowed.value) { + return false; + } + + if (usage != str_sign) { + return true; + } + + return ( + RNPLib.getSecretAvailableFromHandle(key) && + RNPLib.isSecretKeyMaterialAvailable(key) + ); }, getSuitableSubkey(primary, usage) { @@ -2406,7 +2457,7 @@ let use_sub = this.getSuitableSubkey(senderKey, str_sign); if (!use_sub && !this.isKeyUsableFor(senderKey, str_sign)) { - throw new Error("no suitable subkey found for " + str_sign); + throw new Error("no suitable (sub)key found for " + str_sign); } if (args.encrypt) { @@ -2855,6 +2906,63 @@ return result; }, + /** + * The RNP library may store keys in a format that isn't compatible + * with GnuPG, see bug 1713621 for an example where this happened. + * + * This function modifies the input key to make it compatible. + * + * If this function decides that a modification is necessary, + * it will remove encryption (protection) from the key. + * + * The caller must ensure to protect the returned key. + * + * At the time of writing this function, the only existing caller + * always applies protection after calling this function. + */ + ensureECCSubkeyIsGnuPGCompatible(tempKey, pw) { + let algo = new ctypes.char.ptr(); + if (RNPLib.rnp_key_get_alg(tempKey, algo.address())) { + throw new Error("rnp_key_get_alg failed"); + } + let algoStr = algo.readString(); + RNPLib.rnp_buffer_destroy(algo); + + if (algoStr.toLowerCase() != "ecdh") { + return; + } + + let curve = new ctypes.char.ptr(); + if (RNPLib.rnp_key_get_curve(tempKey, curve.address())) { + throw new Error("rnp_key_get_curve failed"); + } + let curveStr = curve.readString(); + RNPLib.rnp_buffer_destroy(curve); + + if (curveStr.toLowerCase() != "curve25519") { + return; + } + + let tweak_status = new ctypes.bool(); + let rc = RNPLib.rnp_key_25519_bits_tweaked(tempKey, tweak_status.address()); + if (rc) { + throw new Error("rnp_key_25519_bits_tweaked failed: " + rc); + } + + // If it's not tweaked yet, then tweak to make it compatible. + if (!tweak_status.value) { + rc = RNPLib.rnp_key_unprotect(tempKey, pw); + if (rc) { + throw new Error("rnp_key_unprotect failed: " + rc); + } + + rc = RNPLib.rnp_key_25519_bits_tweak(tempKey); + if (rc) { + throw new Error("rnp_key_25519_bits_tweak failed: " + rc); + } + } + }, + async backupSecretKeys(fprs, backupPassword) { if (!fprs.length) { throw new Error("invalid fprs parameter"); @@ -2979,6 +3087,7 @@ } try { + this.ensureECCSubkeyIsGnuPGCompatible(sub_handle, internalPassword); if ( RNPLib.rnp_key_protect( sub_handle, diff -Nru thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/modules/RNPLib.jsm thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/modules/RNPLib.jsm --- thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/modules/RNPLib.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/modules/RNPLib.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -1571,6 +1571,14 @@ ctypes.uint32_t.ptr ), + rnp_key_valid_till64: librnp.declare( + "rnp_key_valid_till64", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint64_t.ptr + ), + rnp_uid_is_valid: librnp.declare( "rnp_uid_is_valid", abi, @@ -1611,6 +1619,29 @@ ctypes.size_t ), + rnp_key_25519_bits_tweaked: librnp.declare( + "rnp_key_25519_bits_tweaked", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_key_25519_bits_tweak: librnp.declare( + "rnp_key_25519_bits_tweak", + abi, + rnp_result_t, + rnp_key_handle_t + ), + + rnp_key_get_curve: librnp.declare( + "rnp_key_get_curve", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + rnp_result_t, rnp_ffi_t, rnp_password_cb_t, diff -Nru thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.js thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.js --- thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.js 2022-04-15 07:49:21.000000000 +0000 @@ -288,10 +288,16 @@ document.getElementById("importFromClipbrd").disabled = !enigGetClipboard(); - for (let item of document.querySelectorAll(".requires-key-selection")) { + for (let item of document.querySelectorAll( + ".requires-single-key-selection" + )) { item.disabled = keyList.length != 1; } + for (let item of document.querySelectorAll(".requires-key-selection")) { + item.disabled = keyList.length == 0; + } + // Disable the "Generate key" menu item if no mail account is available. document .getElementById("genKey") @@ -1522,8 +1528,11 @@ let keyObj = gKeyList[keyNum]; let uidAdded = 0; - for (let i = 1; i < keyObj.userIds.length; i++) { + for (let i = 0; i < keyObj.userIds.length; i++) { if (keyObj.userIds[i].type === uidType) { + if (keyObj.userIds[i].userId == keyObj.userId) { + continue; + } ++uidAdded; this.keyViewList.splice(realRow + uidAdded, 0, { rowType: uidType, diff -Nru thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.xhtml thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.xhtml --- thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.xhtml 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/ui/enigmailKeyManager.xhtml 2022-04-15 07:49:21.000000000 +0000 @@ -138,7 +138,7 @@ @@ -178,25 +178,24 @@ - + @@ -209,10 +208,16 @@ - - - + + diff -Nru thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/ui/keyDetailsDlg.js thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/ui/keyDetailsDlg.js --- thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/content/ui/keyDetailsDlg.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/content/ui/keyDetailsDlg.js 2022-04-15 07:49:21.000000000 +0000 @@ -286,8 +286,11 @@ } function createUidData(listNode, keyDetails) { - for (let i = 1; i < keyDetails.userIds.length; i++) { + for (let i = 0; i < keyDetails.userIds.length; i++) { if (keyDetails.userIds[i].type === "uid") { + if (keyDetails.userIds[i].userId == keyDetails.userId) { + continue; + } let item = listNode.appendItem(keyDetails.userIds[i].userId); item.setAttribute("label", keyDetails.userIds[i].userId); if ("dre".search(keyDetails.userIds[i].keyTrust) >= 0) { @@ -540,7 +543,7 @@ }, }; -function createSubkeyItem(subkey) { +function createSubkeyItem(mainKeyIsSecret, subkey) { // Get expiry state of this subkey let expire; if (subkey.keyTrust === "r") { @@ -552,7 +555,8 @@ } let subkeyType = ""; - if (subkey.secretAvailable && !subkey.secretMaterial) { + + if (mainKeyIsSecret && (!subkey.secretAvailable || !subkey.secretMaterial)) { subkeyType = "(!) "; } if (subkey.type === "pub") { @@ -617,10 +621,12 @@ function SubkeyListView(keyObj) { this.subkeys = []; this.rowCount = keyObj.subKeys.length + 1; - this.subkeys.push(createSubkeyItem(keyObj)); + this.subkeys.push(createSubkeyItem(keyObj.secretAvailable, keyObj)); for (let i = 0; i < keyObj.subKeys.length; i++) { - this.subkeys.push(createSubkeyItem(keyObj.subKeys[i])); + this.subkeys.push( + createSubkeyItem(keyObj.secretAvailable, keyObj.subKeys[i]) + ); } } diff -Nru thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js --- thunderbird-91.7.0+build2/comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js 2022-04-15 07:49:21.000000000 +0000 @@ -224,3 +224,55 @@ "should obtain key ID of encryption subkey" ); }); + +add_task(async function testSecretForPreferredSignSubkeyIsMissing() { + let secBlock = await IOUtils.readUTF8( + do_get_file( + `${keyDir}/secret-for-preferred-sign-subkey-is-missing--a-without-second-sub--sec.asc` + ).path + ); + + let cancelPassword = function(win, keyId, resultFlags) { + resultFlags.canceled = true; + return ""; + }; + + let importResult = await RNP.importKeyBlockImpl( + null, + cancelPassword, + secBlock, + false, + true + ); + + Assert.ok(importResult.exitCode == 0); + + let pubBlock = await IOUtils.readUTF8( + do_get_file( + `${keyDir}/secret-for-preferred-sign-subkey-is-missing--b-with-second-sub--pub.asc` + ).path + ); + + importResult = await RNP.importKeyBlockImpl( + null, + cancelPassword, + pubBlock, + true, + false + ); + + Assert.ok(importResult.exitCode == 0); + + let primaryKey = await RNP.findKeyByEmail( + "", + false + ); + + let signSubKey = RNP.getSuitableSubkey(primaryKey, "sign"); + let keyId = RNP.getKeyIDFromHandle(signSubKey); + Assert.equal( + keyId, + "625D4819F02EE727", + "should obtain key ID of older, non-preferred subkey that has the secret key available" + ); +}); diff -Nru thunderbird-91.7.0+build2/comm/mail/locales/en-US/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/comm/mail/locales/en-US/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/comm/mail/locales/en-US/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/locales/en-US/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:49:21.000000000 +0000 @@ -84,7 +84,7 @@ .acceltext = { ctrl-cmd-shift-pretty-prefix }{ trigger-attachment-picker-key } # $count (Number) - the number of attachments in the attachment bucket -attachment-bucket-count = { $count -> +attachment-bucket-count-value = { $count -> [1] { $count } Attachment *[other] { $count } Attachments } diff -Nru thunderbird-91.7.0+build2/comm/mail/locales/l10n-changesets.json thunderbird-91.8.1+build1/comm/mail/locales/l10n-changesets.json --- thunderbird-91.7.0+build2/comm/mail/locales/l10n-changesets.json 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/locales/l10n-changesets.json 2022-04-15 07:49:21.000000000 +0000 @@ -8,7 +8,7 @@ "win32", "win64" ], - "revision": "162654a20c86192e124df9766ec5ecd54143d085" + "revision": "2301434270b060c96b796a84843414f71c1539e3" }, "ar": { "pin": false, @@ -19,7 +19,7 @@ "win32", "win64" ], - "revision": "3be417e9326ebc9e369fc77f1fd98481a39b07cf" + "revision": "a750da883acff8542222b7db4beaacced984d326" }, "ast": { "pin": false, @@ -30,7 +30,7 @@ "win32", "win64" ], - "revision": "41dcea23a9d890ee00cb4cc3797559fe461244bc" + "revision": "ecdc8e82db16f6bc84e5184d67fec27e9db5ae8a" }, "be": { "pin": false, @@ -41,7 +41,7 @@ "win32", "win64" ], - "revision": "d8cbc47ea02faca8963bf8f62df82086c294ff22" + "revision": "891f44dca501f396bbf4ba836abf18742420601f" }, "bg": { "pin": false, @@ -52,7 +52,7 @@ "win32", "win64" ], - "revision": "19ee7b31e0becafa054013a3c8c09844638f244c" + "revision": "9de7fdc78bae439f15788d7a777c83b0de4d5872" }, "br": { "pin": false, @@ -63,7 +63,7 @@ "win32", "win64" ], - "revision": "a9e3b8ba10759c8a4f7da6b7970911ded7d04ad6" + "revision": "d5ecbe84bbe46b6372e5da06fcd02b7b8e872f8e" }, "ca": { "pin": false, @@ -74,7 +74,7 @@ "win32", "win64" ], - "revision": "caf5515093962f3f92c92aea68dacd4c3e520a8d" + "revision": "c2c32a823171f88691555d9ad522227f79d9ad9c" }, "cak": { "pin": false, @@ -85,7 +85,7 @@ "win32", "win64" ], - "revision": "0bbd8b94c9c02fa5ec6a3e5fd3bf3e69b0432829" + "revision": "1251a704bb80ccf0c0bb18bd3d5a7047639e5d07" }, "cs": { "pin": false, @@ -96,7 +96,7 @@ "win32", "win64" ], - "revision": "ae677a6bee277f507e673c3fcd2d56088b2caafb" + "revision": "18580ca702ca9b40257aa0d9b711b47718552d7b" }, "cy": { "pin": false, @@ -107,7 +107,7 @@ "win32", "win64" ], - "revision": "5fff82812b9817b2f616a1e6e134e528c2a24c9d" + "revision": "8a8b0bab6bec9178c672199b548c2bb5133f9d3c" }, "da": { "pin": false, @@ -118,7 +118,7 @@ "win32", "win64" ], - "revision": "4595dd6f7ed91af507076eb0a95a44f4d0646404" + "revision": "edf15c1eaf23bb791ec54de5b68dbda766c4b622" }, "de": { "pin": false, @@ -129,7 +129,7 @@ "win32", "win64" ], - "revision": "d3fca46cd495000d26fd26d3a2776b8f4dae786c" + "revision": "e480a5cc963f95fb72810b525140c63661929101" }, "dsb": { "pin": false, @@ -140,7 +140,7 @@ "win32", "win64" ], - "revision": "611248df8f629860d012cbc8f3a36acfd8744b46" + "revision": "53cc18a5c81992a65e435e8ee3b976cf4051c1f1" }, "el": { "pin": false, @@ -151,7 +151,7 @@ "win32", "win64" ], - "revision": "fb7a8113c5b26216bde957c4a63ff0e1a32dafa7" + "revision": "9a427722011a064b9148d5db31cece3148568c16" }, "en-CA": { "pin": false, @@ -162,7 +162,7 @@ "win32", "win64" ], - "revision": "501d80026e4fdeac79e20b41cb8087c7ec3c3ba2" + "revision": "2b8cac4abc75ebecf6f31bd40364638cd6fac62b" }, "en-GB": { "pin": false, @@ -173,7 +173,7 @@ "win32", "win64" ], - "revision": "ec99571b02068fd4bf160416b5b7e35379c899a2" + "revision": "428e1109220e34baf1dee5c8e3398dac9a664a5a" }, "es-AR": { "pin": false, @@ -184,7 +184,7 @@ "win32", "win64" ], - "revision": "d190464e290f1cfc89a7ca26cadbd523d0c89e6c" + "revision": "2a1f6589c551823a2a81c9440e53ce1db788bdc3" }, "es-ES": { "pin": false, @@ -195,7 +195,7 @@ "win32", "win64" ], - "revision": "46729ef124e5cf1f0a3e85d50c16a069602cfed2" + "revision": "184451ad84e4d1c83b1316673b12623ff6f42561" }, "et": { "pin": false, @@ -206,7 +206,7 @@ "win32", "win64" ], - "revision": "b7a8b9f6c9965756a7a3127fcc1b21375449f1ad" + "revision": "0484a0ca8c2361739ecb53997453f64a255771f6" }, "eu": { "pin": false, @@ -217,7 +217,7 @@ "win32", "win64" ], - "revision": "863a0a1a315b55c18694e29430c272baba355b4c" + "revision": "853864647f080a3134ecc293b3f6fe5561088cb5" }, "fi": { "pin": false, @@ -228,7 +228,7 @@ "win32", "win64" ], - "revision": "6e37410128f2d675c3414ba9c6341af81b4521ff" + "revision": "17521863b0bb9290b62eae9fd7a60840dae3df24" }, "fr": { "pin": false, @@ -239,7 +239,7 @@ "win32", "win64" ], - "revision": "ce1d665cec91d4d29160860dba2350f22f2f4df7" + "revision": "b487c59d8a04c5a03b42b9c6a874650963e15a87" }, "fy-NL": { "pin": false, @@ -250,7 +250,7 @@ "win32", "win64" ], - "revision": "e488deb4c709d26af77adbcbd922058bbb28d456" + "revision": "1320cdf1fb450ea692f58d211bc5f79c4396f3e4" }, "ga-IE": { "pin": false, @@ -261,7 +261,7 @@ "win32", "win64" ], - "revision": "2d955174d7ab6068656b2f02e4d8c689bb2399bf" + "revision": "e3bb3a295b7ba924bfdd725eefd3e9de43e2a396" }, "gd": { "pin": false, @@ -272,7 +272,7 @@ "win32", "win64" ], - "revision": "49032dc335b8b5e9ecd10435f878598bffa6541a" + "revision": "39b62325a674ed227e2bdea12ad67491dc3a0f51" }, "gl": { "pin": false, @@ -283,7 +283,7 @@ "win32", "win64" ], - "revision": "d8761e8f84efac80d6a7482931a01cecd66dd60d" + "revision": "9e100a5adeeac43eaf16fa13c976bee29e1f5dea" }, "he": { "pin": false, @@ -294,7 +294,7 @@ "win32", "win64" ], - "revision": "3385ae23e3b569ba9c0c1aca4df25277b81a108e" + "revision": "4c851305adea679c3b54f28c696dbe8f147a65f6" }, "hr": { "pin": false, @@ -305,7 +305,7 @@ "win32", "win64" ], - "revision": "a01b7ce3515d0b2f05e473625148f11a264da0a2" + "revision": "de15ddccd573c9f26818fb4b04769eff085b5c9b" }, "hsb": { "pin": false, @@ -316,7 +316,7 @@ "win32", "win64" ], - "revision": "f137d0e6746dc23beff4745474df87c33fae353b" + "revision": "e786baca552a4fcc22dfc2e9dc288254733b766a" }, "hu": { "pin": false, @@ -327,7 +327,7 @@ "win32", "win64" ], - "revision": "39e18e316a85b5aaada8c560d51317b5e28b77d8" + "revision": "b642ef82d64a019a9ad87c9921d184b001aaecdb" }, "hy-AM": { "pin": false, @@ -338,7 +338,7 @@ "win32", "win64" ], - "revision": "41e938f8ebf1581d1bc76bd088fc1ac43bb83e0b" + "revision": "ed25a859be4d235645dee61830812b93d34ffe94" }, "id": { "pin": false, @@ -349,7 +349,7 @@ "win32", "win64" ], - "revision": "4d4de9751872149e1c99dcfce2b7ce4835b65589" + "revision": "df459c5785231b35390b635d9f0a8486496d45e8" }, "is": { "pin": false, @@ -360,7 +360,7 @@ "win32", "win64" ], - "revision": "d7a3076075faa159db53da86719dabb4a75e75eb" + "revision": "8623be99f76ba78853d069a7bae70945423271ce" }, "it": { "pin": false, @@ -371,7 +371,7 @@ "win32", "win64" ], - "revision": "3448943cfadfc5a361bd367c7e6be58f86cc61a1" + "revision": "f5032961c31b0410328957d45568fd910bfca113" }, "ja": { "pin": false, @@ -381,14 +381,14 @@ "win32", "win64" ], - "revision": "c4be75596e316966ab1dc9857a9be6b0a7bc2ef9" + "revision": "004f1baf082802d86a609dcb312538a19c33033b" }, "ja-JP-mac": { "pin": false, "platforms": [ "macosx64" ], - "revision": "476eca379b8b21857655d6c23908b3e2a1b09aee" + "revision": "be1ff154a4b4a7e5eac1ecdec92ca292fd1afe5c" }, "ka": { "pin": false, @@ -399,7 +399,7 @@ "win32", "win64" ], - "revision": "2d66f0c2bd7a06ac1ad6ad02a09a26ff1e60e3cb" + "revision": "81337947d776d2fed44bb804415cb3e84e38bd30" }, "kab": { "pin": false, @@ -410,7 +410,7 @@ "win32", "win64" ], - "revision": "409893635bedbe52fa8b85784844e15756d4a8fd" + "revision": "2a21776caf4c44fc8fc0e7d7b2330c02da38dd86" }, "kk": { "pin": false, @@ -421,7 +421,7 @@ "win32", "win64" ], - "revision": "c68316baa4a0dd041abb4e8efd557339fb0d9cb4" + "revision": "51a219b2c24298b520ea028699adf87edc783385" }, "ko": { "pin": false, @@ -432,7 +432,7 @@ "win32", "win64" ], - "revision": "88096d30e35f344fcb61f08900340b31fca79cc7" + "revision": "1ce43f4e7d36e54e34ee0297667f7febdf861faf" }, "lt": { "pin": false, @@ -443,7 +443,7 @@ "win32", "win64" ], - "revision": "6a447408fe67e37ee56a85d8bea523219dac52e1" + "revision": "32f2256b09716d2e85f72b47964a6350bb86f870" }, "lv": { "pin": false, @@ -454,7 +454,7 @@ "win32", "win64" ], - "revision": "0059bd3f14ced8ec1ef0f2765b655fe4ee537e91" + "revision": "bd7d759b7f84fe6b003c1f7a898ad93b04b86eef" }, "ms": { "pin": false, @@ -465,7 +465,7 @@ "win32", "win64" ], - "revision": "ec4c315ae032575bed799d8faa57dd4441e5bd9e" + "revision": "fea340feae8901443fb3a5217df25c89419c451f" }, "nb-NO": { "pin": false, @@ -476,7 +476,7 @@ "win32", "win64" ], - "revision": "490c2d401359fd2204ad7aa806a73107f3befc27" + "revision": "4b405501b8d11e73e395b21958cf28f011c2cc01" }, "nl": { "pin": false, @@ -487,7 +487,7 @@ "win32", "win64" ], - "revision": "3f55dcbe90edd21965795b84a1601229a36fd4d1" + "revision": "098cfe035eb91d43a4e156d341f8b209057acb49" }, "nn-NO": { "pin": false, @@ -498,7 +498,7 @@ "win32", "win64" ], - "revision": "6a1a6bca02e894a9e989bdc33813025ecd5acd20" + "revision": "54dd71db250efe1ce1e839b954ec3def1b445705" }, "pa-IN": { "pin": false, @@ -509,7 +509,7 @@ "win32", "win64" ], - "revision": "b28bb037d4687370eebb7a892982b31bddea32b0" + "revision": "3d4b229a30cd2c7a864cc2537fc090062c520ad5" }, "pl": { "pin": false, @@ -520,7 +520,7 @@ "win32", "win64" ], - "revision": "3193b4b820e7c37bdb9153ab9c525f18210a501a" + "revision": "e22eec04250ce00cdfa8abf61fc4652a8d1a4cae" }, "pt-BR": { "pin": false, @@ -531,7 +531,7 @@ "win32", "win64" ], - "revision": "ce1ab16cc1acd0fa7ae898feeba46c6d497fe981" + "revision": "55f159519451642392bd00e90ca39b6701bfe069" }, "pt-PT": { "pin": false, @@ -542,7 +542,7 @@ "win32", "win64" ], - "revision": "e0910097929ee117291ede6675c6e0add124221b" + "revision": "e27715b7ff83861241314aac559e6095ae3cef33" }, "rm": { "pin": false, @@ -553,7 +553,7 @@ "win32", "win64" ], - "revision": "cdce5683cd6621c0ca31eb6b6ffd209481fa3c85" + "revision": "716264f686e48a005284946e48916254b4d7738a" }, "ro": { "pin": false, @@ -564,7 +564,7 @@ "win32", "win64" ], - "revision": "ba7fe96d6c98e01a48f442d520c39d119c7e0727" + "revision": "c104292fc7dabaa5001db8ae1b0628314b3ad9af" }, "ru": { "pin": false, @@ -575,7 +575,7 @@ "win32", "win64" ], - "revision": "dc6d46ab977eb359c21a0f6dfe5b22e1fa60fda0" + "revision": "19e188f9318b9beb6a0a2a432776866ae54b41e6" }, "sk": { "pin": false, @@ -586,7 +586,7 @@ "win32", "win64" ], - "revision": "588464d4ecd69c9a12ffd0e41ccb5e4a7f16e25e" + "revision": "8f6e8065a1a7f575d8f3cc742831dd2ffd0343d6" }, "sl": { "pin": false, @@ -597,7 +597,7 @@ "win32", "win64" ], - "revision": "d5882d14036a97883f3aedbaa93e0d01720e0c8f" + "revision": "b5c6405a8fb26d32acb46f7d6717c49934fb05a6" }, "sq": { "pin": false, @@ -608,7 +608,7 @@ "win32", "win64" ], - "revision": "05efafdd60c5a69d6d75adf8ccb97c5b07aee239" + "revision": "5b81bb3f636b3ba94b5b4ad6bf658322751ce133" }, "sr": { "pin": false, @@ -619,7 +619,7 @@ "win32", "win64" ], - "revision": "e7c7978d2fd74f4e2098253a41b099604b88d61b" + "revision": "0deba25cdae68c4f1510174614f1eb76a390274e" }, "sv-SE": { "pin": false, @@ -630,7 +630,7 @@ "win32", "win64" ], - "revision": "30479c6d22a77f896ea16e6266392711ea79a854" + "revision": "71e47714e048f96da8d333be759a4d5889e4e55d" }, "th": { "pin": false, @@ -641,7 +641,7 @@ "win32", "win64" ], - "revision": "b6c8c65ece954839a983d48aa92a348b84867fa7" + "revision": "8bfbdb39ef3d3d041db98ad672b555a617575e6e" }, "tr": { "pin": false, @@ -652,7 +652,7 @@ "win32", "win64" ], - "revision": "810f0ebde4235bf764070b3f0628cfd712446aa3" + "revision": "a2bfbc116e8e57837395e09d8f8e0a96b8b837c6" }, "uk": { "pin": false, @@ -663,7 +663,7 @@ "win32", "win64" ], - "revision": "51ac98096a376ade0e29ba477d20e86e8e553eaa" + "revision": "1d987f6fa4abacd5db2018990756309a30df0f4d" }, "uz": { "pin": false, @@ -674,7 +674,7 @@ "win32", "win64" ], - "revision": "f8e8cc127eaf07ab77bf51c37ec494d2721e8d2e" + "revision": "f2b59b0a2d0b7fbb91b2fcb519db4db8b2e70d9a" }, "vi": { "pin": false, @@ -685,7 +685,7 @@ "win32", "win64" ], - "revision": "e24285029832c0cc588e8e12aa2212dff982d623" + "revision": "3c9cce6136a1876644b6465be037c1f8da08d385" }, "zh-CN": { "pin": false, @@ -696,7 +696,7 @@ "win32", "win64" ], - "revision": "12b859d962f2252d012eb9ce4e8c3a8e1b31c68d" + "revision": "59dfbde33841356637a31ec79ff2796df732a889" }, "zh-TW": { "pin": false, @@ -707,6 +707,6 @@ "win32", "win64" ], - "revision": "74f0fae3d31431cf742b41a2832a0e8b3bdabce9" + "revision": "d6a70a4a85be1ea53a167f6891f494645d6f86e6" } } \ No newline at end of file diff -Nru thunderbird-91.7.0+build2/comm/mail/modules/MailMigrator.jsm thunderbird-91.8.1+build1/comm/mail/modules/MailMigrator.jsm --- thunderbird-91.7.0+build2/comm/mail/modules/MailMigrator.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/modules/MailMigrator.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -127,7 +127,7 @@ _migrateUI() { // The code for this was ported from // mozilla/browser/components/nsBrowserGlue.js - const UI_VERSION = 30; + const UI_VERSION = 32; const MESSENGER_DOCURL = "chrome://messenger/content/messenger.xhtml"; const MESSENGERCOMPOSE_DOCURL = "chrome://messenger/content/messengercompose/messengercompose.xhtml"; @@ -613,6 +613,12 @@ Services.prefs.clearUserPref("ui.systemUsesDarkTheme"); } + if (currentUIVersion < 32) { + this._migrateIncomingToOAuth2("imap.gmail.com"); + this._migrateIncomingToOAuth2("pop.gmail.com"); + this._migrateSMTPToOAuth2("smtp.gmail.com"); + } + // Update the migration version. Services.prefs.setIntPref(UI_VERSION_PREF, UI_VERSION); } catch (e) { diff -Nru thunderbird-91.7.0+build2/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--a-without-second-sub--sec.asc thunderbird-91.8.1+build1/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--a-without-second-sub--sec.asc --- thunderbird-91.7.0+build2/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--a-without-second-sub--sec.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--a-without-second-sub--sec.asc 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,129 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQVYBFLtfH4BDAC9ad3c2rD5jOZ0ynonf90JzXHvPeoksmj7fMT2KX3FTg+lzdKG +40Pxk3/53/otqvYOvw8A6Pb18fOLlTvkTMQ2CFjRqd4oydFKHZjM+gWBoyFWMq2X +PRIrYw6n3LJb6/wfula4rgnCVE4gOSkTBtto0yJCZtHQMh2blBtq2W/jNJs+OEpf ++LLDoOhO7B31HdWiVHuQTMG7sZwrH6MwuZKU0tYuwoA/Eeznuy9X42IKc7WEA3fj +0A7Eme8Bw8lnZ1kiLe6jgAA1DxKBbu2dB3ParC+d97FZ6pWwnd0JiWZ7ws5F+KBF +r4RSnJ552xUjrmiFehbAIZ1I9EY9m7eQ62lhOZAa/WfE7WA7hyufgpf0e8CR01Tj +60ckFrfoTXnumWOASDJLUaGaGo9J2yjbBjcut8Nn2OfXysofzVevkrCi/zLFHWPa +mjoa+M2R7vBl5alk6XoLSN0SBzDLeXpMdVfNBqLrlC4QbqI2oakkqEpX2VEV3f9Z +ozlizzNMYSWp50UAEQEAAQAL/RwJ/29RqlAOxRC15nZRbcGlOX/+bNpI1NShqDB+ +fOFHyHY1bTxNiUHKIXA2cTzwaWNOciSi1+gZjIF1snt9x6/t9WP4Huxvz70Ge5eg +TU9e/DDb6KmSP03P6Jv9xiNoYBa8SVkmXkh3nWcUvxlTcwhl9NTajqWgvZRJzPM4 +w+Dg6ThBMfVaBfCCsdD5EAg4heb1VaNLUYR86s7RbKFqXyILwewDG+P6PdUh9wSu +ItXEQjMMJmPBaWY+GUzsFDTr7dsvFCRD2rJhaTlFaJhfN2F5dSrBwGQvNlDueity +DbGBvYU6KzOuHwo37/dpRQ7NdQk9OGN0foLE7t5MxiCVpnzdtTXO0ypbPU9xSpkP +Zo7c2ufPGx2HFVUW/9GKCruxR/aLfXCzkYC1ZbO26tjjp4YA0lQMOtCormjMFiw4 +OR3rISCvAuQ106nvjyfBs6UmtYJExaFdzERZqw8+Z/cT5lNpptHxtRQIN1eLktMv +d8tWiDAHCurRqbthAJ/FQAs5gwYA1L32mx0YpfRA6S9DNAElR+s+ffkcr3I7dj5A +RsAlsT0OXqFFfA007kB1+13Aww2UFnDI2gVkEWsFa75YUY9iUKOjllFyT6HFJiyq +NzTv1V96OJOzrgfIzBdttZhb1YdlG7qnHQt7u8jeBCjVaB+7wzRCk0dknG/i9Qqz +y4huWbu1KOlRE4FsrqguYR6e/O2KVBdvAkqlp9KcIWUoXyA7p3bYnQgqV6qGUHgM +YZh010rMXpmtqKSIyjr4PekuPhI7BgDj7ZDLjLeAOCH3fdNKYV02oBlEpio4P5RR +EoShoyiocczBXUfRolgJyO+8+4eKjs+xJNYiQDeZr8MrMkodXWXZT75uiBKBmDEN +jaTMFp9C8nubmZ0ai7f4R8d49+XHy77h2yMTiwcNs2iLfSPWXl0VS8pFS4XfobMG +ixhOG6p5Y2Rjc/t4uEDV+n11em3BGD5+d4/8WvBw+b0UVIrHnWbKCWDmE9FvB/fc +HG9lDExvwJn++COsyK+lG2NlZJby1H8F/21hYNQGeFIBNSeDrPxRC4tgHHOA1LH0 +9qgEek6Zq9Ag3zblY4r3c5AnV4dMu7lnzseFUnBpb73SxsRD7e+6rg59wpmDeMs4 +ajpM9YLmVdPgYmn6OjpxdfmKgYpMZTjisGGFm7XbKKQ0GEFuo3oQggZYMuQ+d3eK +cC+89gMU0eyP0gRg75feJpxlM158B6uVYB8pfap2d2yfeadJPcBSSdoVuwl2zQTK +ECP46uW++mhN2gBVU4iyMphyrclOPbe8ItgBtDdzZWNyZXQtZm9yLXByZWZlcnJl +ZC1zaWduLXN1YmtleS1pcy1taXNzaW5nQGV4YW1wbGUuY29tiQHOBBMBCgA4FiEE +cagS43SiqCdNHP5mW1w0QlGl2n4FAlLtfH4CGwMFCwkIBwIGFQoJCAsCBBYCAwEC +HgECF4AACgkQW1w0QlGl2n7aywwAgWr9bhgNwzesG7pJo2G0v5E/XlznEInkSxCl +xTuRLg6uzQnLnFB4dCkN4TNhfrVkPl+PZS7BM9D84VwIjO7KbSnDILXt/eOi1uYk +EdDLKrTxc7OAQMmnktvw3t8xsul+HvjY5EEYMz73+TWS5DHPuOX8B3gtzOnTDMfn +PrslkmakypoQe+CAsjh6JZoHt19RIlvVg8xr8Gx0SeXlp0ZO+SA52Wb/Tp1sTpXV +H8QBf5iOj++9wxaf6kJvRvdZqtxgqBSTaq3/w1z4Achav5/fofiQgQaJ2A02r4Uj +RleUfMjF0RiFbu7XS7XXBvQ8Qnt00J0I91v0WnaagheDEyRezOoKYXh7ArU9X2b6 +uxumXDB1eSoR8HUMDxsEtmBEVxoXH8DhqDkiYXzrfm9GKdrIAzz/Miwxqb9G2XGq +oX2VRBkpnGoaNG6K6a2v3kvfSZFKXCjfiRDVNeK6XL7f/VOqcO/gX+6UJHlqytNf +ONloSdzOzWmgP9MH0vZxbeqEppVOnQVYBFLtfH4BDAC2k4vdz3B1pZfwC0jzWeZC +uFLxZEBHKBJlt6q19PGovRZz3IXZE/pHNAsfSYZn82eJa9OJ9+BIUSjkxzA4Drnf +Vg5mLk+bmy/LcH2IBVxZTBSiSjWkZijBqLjPDL+DKOp04LUYEoRFdmvC8pzDYdy3 +Fei32TBlie/VLIOHJY0YHjziYscIu6OhTnRsx2AcAeCxPr8BWxWWpLzoK1Bg3Ka3 +TnI9AqzqEFs0QChVuti7gzz2ItGhE6GUP6LyHVQJYRZgCyGzCxw2ObM3lsRBIpLU +i0S0bcwfnaI8ZEJtRJp0ogdJvgzdnPa4AS93otmAsy0EeypKtW32yDH+bz9ddk4S +if7Mat20m5dNNxFGecCGKUnk8JooiFg/5NmBOkCOuKV+foNSkbf+Ue++Yg3KVW5J +ewpTJzgBENHKJKDYhUCnTJ4R38Yb/8Ub7caXibWJ4t/cQ06mymnm61rthQ57adz3 +ChC0+r+q1zj/eKI+rPyMWcRRUFWpZBBVds1Woje23jEAEQEAAQAL+wSYboJ/73gl +ma89AHpAFLawlCVfaSsFVh+1bZSAgKHnNwDF7+BGs4Ot6psALzPv/WbZBgE8sgpt +8Qgfn54EmF73x/tgTmiHsZ52s5EsNd6pRqJuWN7tQ5i6xAKRowMkkTCtjH9ZbXcA +X95ffAzCqoMY+ANjIgfHPtg0M3AQFNbi4XRPCUyV6PylGHL5unh//1lkv3rjsZWZ +6keTegWjHibiYIeauPKYBGyqcf1061I+b5cQKau6zlQIfUPn8zLcfMBd0d09QOAM +JU5nPEMtWZKbow67eaCN66k23vI9bNbKMV+1et85gYa6dlgPYqcVTCNrNrcrRnlB +eXbOTWVqVPkuDZWpYrC9dYVxF7CQvSOHOCVwZNojirMCJTYhCwsvL7GOp7UPIfiP +2OOWclBBCpNsYDRxqTqp8KarlZPxl/bZkkcYDX6zWLN84ArAfUsGJsYHUiOQInUi +UKG7R+GLsmmzLux1yBpkaQI8vJU9TBUZUrbu5cE227UzwkLlg5Ul4QYA0/iGHn6x +fQh3u/fhdHkr1Noc7WbbPQopkdfAtOTZF16b6PG/JGRjgp01/bjCm7pc27JwjOuW +e09SgNJ1zXfFvRa0XgOC7ZX22CAxT0nT/OUYtMa4cg2HndvDikOTOjDwKGjMzvuQ +Yd5O4/NxkYVwdEEBy/MDsT2hUMgHXa22JGRGveTWZS2Pk1eWsoJPTcxDttE8a/Na +jtqzNpGh6YZe0FyvcQmi7UIIeTm/1Rv4qc15DgaLms51fEzUtLJEIT5hBgDcf/uW +PMQRVCxkexQgINUzqx2w2VEUnkgyMSaiTuKhJT90VhKy+9Yb1YGRKGA/SsdWhV7Y +gxmoT73vbKB68KGIB4RS157jNH5DMlfMXXhuF0QRZm32jU7a4ShP/Do9KsHXCNva +ZKc/DczrLfpnBjMWwS0w93pNQeZI2M1tHp07BMyW2JiNtcGXbz0iWq6tsq2J6JLY +KbnW83KGXCvfLBS0N6qhP6i3fUktWZ17P3g8xLdQlCBii6VVdYRUkeD+kdEGAI8w +K86sWfq+RCKwcNtfEXQZZ8ATOzYDDW0WPodU8suUqXuxEZUw9sG3EquIUSrmCGd9 +fWvAgxfHcE/RPjNn1xT+8soO+CeT84jhCpGcYAiWcOkFuOjYMsBQNSQmuz0GPnJf +OOF8EWkJNXsp2JVZgCkMhBBnFWXM6CVydqaFQ6jspGt/LKsVBTtAxUisrjFB/f1k +DhRd0zknWVZqrK3n0f3WiKgZpaEt8eclCypEsUywPvjah+HEO6LbziLftEBVkNXX +iQG2BBgBCgAgFiEEcagS43SiqCdNHP5mW1w0QlGl2n4FAlLtfH4CGwwACgkQW1w0 +QlGl2n5MeQv9G8ZjWnszJAZa7iF0KnJrRInsrpiduzG2iONb45z1G3arXKkD2sKt +2KL+AgMtLx+/DXHKsoJBNgjXmkM2EYiMUuKTpzsqE9TPNtnu5maZFc+Q0tMK9Ycf +Ot/zLCja0Owxf0975Zg0Cck9JZSDGUqYTtYWaIQ+gID3bvtb9/5yEQ+5KmtdLYUH +/yCeXraZ9y8rodHW91cVLCY0v3r3pgaV5zCB5iw1SwVnAWMqcA1s4oHffwOJTVQb +9OoC+Yq2z4Nk86+wubEqnC+5x76Xqep7jIARRXWeuVufsUcci6YPNWmnHpd8/BPu ++nbvOVVD/X9fhOdxbL0DNymHmbh5zAsNz2l1rm58u8ACxx8UuugukgkKRmIcpxZE +WRLGn7czwjUfluttSDCDDLMC9cP/R9sJyM+QTD+hK2sNCvx4nrHAf8jiDtk1Y+9h +NXIvVXzuRp2W9nPJJopuAAGBvPizZF3Ej3nITJddb423z8+Jb1kAUKzH2wXSzgSh +iPbtdboNhtsinQVYBFT064MBDADPZIdxXmDJJbnSfzgOI8c43YSteEFtJjSmTUo4 +fAMz/4RNk24FmFnnDNTqboE5qFVK7Mf6Zxbmgjo0cQQzPFPJXk9YyuN9Ge5lLeaQ +0fXyfpIYTPbcunqBrbVjMcnI/v+x6O9ma+5c3AzX1CkRm0YrSu9t55Fm/y3bP/2u +L1PVSmAr+AZMhMZf3xP7TZQXwqx1aROdUARAk6zR44JyiopOApCA5vwZsMgg/2rV +t+B9VH430wqkQV53IGINXCum5oMpeBxm+LrzpYnZiUrMLv4uZkmmj/5Mx3+aDfIS +u7+cmvbNzHoRsIBwphUtGD+SNdFr95wXSjxSfA6NNTJWGD1Gi9l2bO2grVq1j7sz +h2QconAPrXv4hB72RxPAZP6gV0jfApb22ihEKi5FuOYY0i4halWBGWOXpseQue26 +fM+XsoS83TwMyk7lAA5a4hVQZDUr/JJjdIJkCtqoxixF+AU7W7w/1vnVgAGai8I1 +QI41KiGkm9F9nU/dCtQmnjuLu3kAEQEAAQAL/RSHN9zh4aSnZlBOpWbI5dRcIODm +0VsTeAyqA9m5dLu15AultzM4lFWJcJ3P2Fyzq9WhwF2pzJt+cnJ0aV0E8Koy+pmo +Y4IjifRb6cGV9slM+/sJyzmn/65MWnL6H6YUj4y1qNSzhEGOynqmlnYWr4hjf3Wa +gUr3oTtdhyexqZOoLALOJxl13wjoVNsAH9OGQnnQr89Xd0RJGccgxO2/htcX6+PG +eVe1pumVPqbu73qYXXH7IseFbOtPukTmRa/cixtv6Dda6FX63k2pfA+xbGTEijx1 +NXsU5Ol7wW1ZrhmJxIPRtTJrRAaPHDJzzx6p6WTEz0d2efe30UCS6aYuWy3yTe56 +TDyMlspHcsyw2Elr+1wthkjrZ1zXgGAP7kQtBmpEwyeSP7Fu49Fw8fSm0D027nbH +SaqN2R/nkuqclFvUfg2WcskBc/Q51/qr2MTNlYWK+/uP7XKhywrzSlzLHnaxrlL3 +ESY1BZkZ9t9Va5sXzWBR2J8ogCMMv1ta9OSMMQYA3muIQo79ZZAnqLUECrHP0cst +3PgfCGxED1aAZ68rlO93+pTA0kHlHURXGLVCLM5jP2UpTfN3oymJbjmr9WvZqcQY +mRvJ9R2SuCH8tb6QZt0pT2nyhHuEwT/TNbtE04wMH2unHhmuavp20MqcFmXudI3b +YEMa9zd51JPMtjB/UpkfXyXeIjjXnkZvbIuu+Ah93Z9xiKjkczEljX+ynFOLGOf5 +KTqDDDXepzO7YMZhIfhYSVLLX4/d5o6q0YLVllR9BgDutDGrnDn87bYl8hUQb7h6 +AkQeimrgqBuZ2B+Ubqq2f6Y52oKV9RS49KKrc+/DNSbME1+2/39W+NIPOuUB69UO +48b9bmSiGOdUR02y9LYaE4qLCDR4gVmERsekf+GnaRFx/00gFgXCWnw1e5emcUPR +W7hfrDzLO4At2vU+kPEbbnvlh64gs+tPz0c5AmdsqwZi000IQsvkzfXMI0LsZVNF +NsAulu9B9lz1BMJ3pb8Hxf47oHAdxX3R0/OocRBXn60F+wcfplWrStRARMGK+/CM +voYZKEWRZ6pk44a/vq1L9/VALUiGRB4XvXdiQK+rOH5vVJRhH9LFTgoM00X+sGZf +r8WBbFl+hBHe5z+SUi916+qLq4+qhz/VwLTRZCZrBgEqxYsu0L4h7jKRL3ifZCV+ +nBf+4ObHXw8gk0+PT+ZuNQ28gslupvayWWcloMxxIT7KPVMvk+D4f4bYzhI0DCGZ +Jbf4F7KOPMlN/ZYiz8jrFeIWeZjA1y0Sy0e6AKaKj4RJA/JriQNsBBgBCgAgFiEE +cagS43SiqCdNHP5mW1w0QlGl2n4FAlT064MCGwIBwAkQW1w0QlGl2n7A9CAEGQEK +AB0WIQRhIYHmBsx+W+KdrGhiXUgZ8C7nJwUCVPTrgwAKCRBiXUgZ8C7nJ0OrC/9S ++9c+9dlCz7ls/Ez8+3fnttL72Ui2VPEgB+KYj71K6Jx/29JFHec2Bl35Si/6NSWx +25rrEbbYtcXQPqu0W7PqAfzytx+GxCdMDUHqMdcxx8mZn4WCYVYwxOhsNMQIZHmz +0noJnHholQ9XsGVWkV9TPyW38zGVC0yHAakrJ5ZFuJN4f7UNydYgwyVtPbVfOryd +7dDPaBNJOPjpgQ2Xuj1p4Ygz0WQZ+FYl8EcV4jzYi085lhuDCjX9gbF5IkIkjLZm +RKpAX3tR8L+d5x8gTuVTZoLrpSDZR0WsSPFhgKKiY/hVo0oPKXoSz1DOygwk1PMS +cEiJ5jbGYvQ+yBJbJO02O4fXTeiKYHONBIhu7fl+49JMXqOscHoKsP7PlCZ87YKq +u6S1h/nHY+vVpbnhV2XDINWpn7d1qsBfewy/plXf5BPB4334ruqclz12DqreHXtO +IzFr6LSTm4pIWia1Nxu03qXwCl9dhhBQCWZ00bnYzL19sWnN6HLdfvTdYxNPzn5T +Ugv8C0Boxbf8lhkiy0+P8Z9JKP0sSRhjKlsoi7hk2artsfcPGOcid7WNP3Ruc+rh +IQADbgjSHnUpJ892XPkJ58yUEPCr0B1+GkV93Lv41Q6UHqDHJOWeWqhOoD/qRT+6 +ZRGGA3BQ2xmxNKphsUx7uBcndQsig0JNCMawH/OklvlBqDMthlOFMeSfhkVvLymy +DtikFrdkYQmo/IrFHe0leeiQ671ZF6MRxtnx6NmtJo29LOquReTU2LZyUJ6q6XEk +daH1Av2c1u0BmIJoHSUgHaxM1wJ7oSE9GfGS9dDyWADAKv1obVb3Zpi5Dzr/oBN+ +ipstAEUYvBlLvaitt3Wvx9/8QUTpqxCQJk2owXE8omY2xH/yBJCiF/ht8+cUKw/a +lbiFAUz9S2ncUC2j1j/myF17obcnrDWKwMbW0BPIkZmIqKyKp4GTL+rEkGiZzqcf +s5zFIgnbiE4E7r3nKR3uc8RbeJ631che4mZjFi43lt7KVOAC+OD2j+tCnPz04f8H +iUE5 +=f5S8 +-----END PGP PRIVATE KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--b-with-second-sub--pub.asc thunderbird-91.8.1+build1/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--b-with-second-sub--pub.asc --- thunderbird-91.7.0+build2/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--b-with-second-sub--pub.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/test/browser/openpgp/data/keys/secret-for-preferred-sign-subkey-is-missing--b-with-second-sub--pub.asc 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,95 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGNBFLtfH4BDAC9ad3c2rD5jOZ0ynonf90JzXHvPeoksmj7fMT2KX3FTg+lzdKG +40Pxk3/53/otqvYOvw8A6Pb18fOLlTvkTMQ2CFjRqd4oydFKHZjM+gWBoyFWMq2X +PRIrYw6n3LJb6/wfula4rgnCVE4gOSkTBtto0yJCZtHQMh2blBtq2W/jNJs+OEpf ++LLDoOhO7B31HdWiVHuQTMG7sZwrH6MwuZKU0tYuwoA/Eeznuy9X42IKc7WEA3fj +0A7Eme8Bw8lnZ1kiLe6jgAA1DxKBbu2dB3ParC+d97FZ6pWwnd0JiWZ7ws5F+KBF +r4RSnJ552xUjrmiFehbAIZ1I9EY9m7eQ62lhOZAa/WfE7WA7hyufgpf0e8CR01Tj +60ckFrfoTXnumWOASDJLUaGaGo9J2yjbBjcut8Nn2OfXysofzVevkrCi/zLFHWPa +mjoa+M2R7vBl5alk6XoLSN0SBzDLeXpMdVfNBqLrlC4QbqI2oakkqEpX2VEV3f9Z +ozlizzNMYSWp50UAEQEAAbQ3c2VjcmV0LWZvci1wcmVmZXJyZWQtc2lnbi1zdWJr +ZXktaXMtbWlzc2luZ0BleGFtcGxlLmNvbYkBzgQTAQoAOBYhBHGoEuN0oqgnTRz+ +ZltcNEJRpdp+BQJS7Xx+AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEFtc +NEJRpdp+2ssMAIFq/W4YDcM3rBu6SaNhtL+RP15c5xCJ5EsQpcU7kS4Ors0Jy5xQ +eHQpDeEzYX61ZD5fj2UuwTPQ/OFcCIzuym0pwyC17f3jotbmJBHQyyq08XOzgEDJ +p5Lb8N7fMbLpfh742ORBGDM+9/k1kuQxz7jl/Ad4Lczp0wzH5z67JZJmpMqaEHvg +gLI4eiWaB7dfUSJb1YPMa/BsdEnl5adGTvkgOdlm/06dbE6V1R/EAX+Yjo/vvcMW +n+pCb0b3WarcYKgUk2qt/8Nc+AHIWr+f36H4kIEGidgNNq+FI0ZXlHzIxdEYhW7u +10u11wb0PEJ7dNCdCPdb9Fp2moIXgxMkXszqCmF4ewK1PV9m+rsbplwwdXkqEfB1 +DA8bBLZgRFcaFx/A4ag5ImF8635vRinayAM8/zIsMam/RtlxqqF9lUQZKZxqGjRu +iumtr95L30mRSlwo34kQ1TXiuly+3/1TqnDv4F/ulCR5asrTXzjZaEnczs1poD/T +B9L2cW3qhKaVTrkBjQRS7Xx+AQwAtpOL3c9wdaWX8AtI81nmQrhS8WRARygSZbeq +tfTxqL0Wc9yF2RP6RzQLH0mGZ/NniWvTiffgSFEo5McwOA6531YOZi5Pm5svy3B9 +iAVcWUwUoko1pGYowai4zwy/gyjqdOC1GBKERXZrwvKcw2HctxXot9kwZYnv1SyD +hyWNGB484mLHCLujoU50bMdgHAHgsT6/AVsVlqS86CtQYNymt05yPQKs6hBbNEAo +VbrYu4M89iLRoROhlD+i8h1UCWEWYAshswscNjmzN5bEQSKS1ItEtG3MH52iPGRC +bUSadKIHSb4M3Zz2uAEvd6LZgLMtBHsqSrVt9sgx/m8/XXZOEon+zGrdtJuXTTcR +RnnAhilJ5PCaKIhYP+TZgTpAjrilfn6DUpG3/lHvvmINylVuSXsKUyc4ARDRyiSg +2IVAp0yeEd/GG//FG+3Gl4m1ieLf3ENOpspp5uta7YUOe2nc9woQtPq/qtc4/3ii +Pqz8jFnEUVBVqWQQVXbNVqI3tt4xABEBAAGJAbYEGAEKACAWIQRxqBLjdKKoJ00c +/mZbXDRCUaXafgUCUu18fgIbDAAKCRBbXDRCUaXafkx5C/0bxmNaezMkBlruIXQq +cmtEieyumJ27MbaI41vjnPUbdqtcqQPawq3Yov4CAy0vH78NccqygkE2CNeaQzYR +iIxS4pOnOyoT1M822e7mZpkVz5DS0wr1hx863/MsKNrQ7DF/T3vlmDQJyT0llIMZ +SphO1hZohD6AgPdu+1v3/nIRD7kqa10thQf/IJ5etpn3Lyuh0db3VxUsJjS/evem +BpXnMIHmLDVLBWcBYypwDWzigd9/A4lNVBv06gL5irbPg2Tzr7C5sSqcL7nHvpep +6nuMgBFFdZ65W5+xRxyLpg81aacel3z8E+76du85VUP9f1+E53FsvQM3KYeZuHnM +Cw3PaXWubny7wALHHxS66C6SCQpGYhynFkRZEsaftzPCNR+W621IMIMMswL1w/9H +2wnIz5BMP6Eraw0K/HiescB/yOIO2TVj72E1ci9VfO5GnZb2c8kmim4AAYG8+LNk +XcSPechMl11vjbfPz4lvWQBQrMfbBdLOBKGI9u11ug2G2yK5AY0EVPTrgwEMAM9k +h3FeYMkludJ/OA4jxzjdhK14QW0mNKZNSjh8AzP/hE2TbgWYWecM1OpugTmoVUrs +x/pnFuaCOjRxBDM8U8leT1jK430Z7mUt5pDR9fJ+khhM9ty6eoGttWMxycj+/7Ho +72Zr7lzcDNfUKRGbRitK723nkWb/Lds//a4vU9VKYCv4BkyExl/fE/tNlBfCrHVp +E51QBECTrNHjgnKKik4CkIDm/BmwyCD/atW34H1UfjfTCqRBXncgYg1cK6bmgyl4 +HGb4uvOlidmJSswu/i5mSaaP/kzHf5oN8hK7v5ya9s3MehGwgHCmFS0YP5I10Wv3 +nBdKPFJ8Do01MlYYPUaL2XZs7aCtWrWPuzOHZByicA+te/iEHvZHE8Bk/qBXSN8C +lvbaKEQqLkW45hjSLiFqVYEZY5emx5C57bp8z5eyhLzdPAzKTuUADlriFVBkNSv8 +kmN0gmQK2qjGLEX4BTtbvD/W+dWAAZqLwjVAjjUqIaSb0X2dT90K1CaeO4u7eQAR +AQABiQNsBBgBCgAgFiEEcagS43SiqCdNHP5mW1w0QlGl2n4FAlT064MCGwIBwAkQ +W1w0QlGl2n7A9CAEGQEKAB0WIQRhIYHmBsx+W+KdrGhiXUgZ8C7nJwUCVPTrgwAK +CRBiXUgZ8C7nJ0OrC/9S+9c+9dlCz7ls/Ez8+3fnttL72Ui2VPEgB+KYj71K6Jx/ +29JFHec2Bl35Si/6NSWx25rrEbbYtcXQPqu0W7PqAfzytx+GxCdMDUHqMdcxx8mZ +n4WCYVYwxOhsNMQIZHmz0noJnHholQ9XsGVWkV9TPyW38zGVC0yHAakrJ5ZFuJN4 +f7UNydYgwyVtPbVfOryd7dDPaBNJOPjpgQ2Xuj1p4Ygz0WQZ+FYl8EcV4jzYi085 +lhuDCjX9gbF5IkIkjLZmRKpAX3tR8L+d5x8gTuVTZoLrpSDZR0WsSPFhgKKiY/hV +o0oPKXoSz1DOygwk1PMScEiJ5jbGYvQ+yBJbJO02O4fXTeiKYHONBIhu7fl+49JM +XqOscHoKsP7PlCZ87YKqu6S1h/nHY+vVpbnhV2XDINWpn7d1qsBfewy/plXf5BPB +4334ruqclz12DqreHXtOIzFr6LSTm4pIWia1Nxu03qXwCl9dhhBQCWZ00bnYzL19 +sWnN6HLdfvTdYxNPzn5TUgv8C0Boxbf8lhkiy0+P8Z9JKP0sSRhjKlsoi7hk2art +sfcPGOcid7WNP3Ruc+rhIQADbgjSHnUpJ892XPkJ58yUEPCr0B1+GkV93Lv41Q6U +HqDHJOWeWqhOoD/qRT+6ZRGGA3BQ2xmxNKphsUx7uBcndQsig0JNCMawH/OklvlB +qDMthlOFMeSfhkVvLymyDtikFrdkYQmo/IrFHe0leeiQ671ZF6MRxtnx6NmtJo29 +LOquReTU2LZyUJ6q6XEkdaH1Av2c1u0BmIJoHSUgHaxM1wJ7oSE9GfGS9dDyWADA +Kv1obVb3Zpi5Dzr/oBN+ipstAEUYvBlLvaitt3Wvx9/8QUTpqxCQJk2owXE8omY2 +xH/yBJCiF/ht8+cUKw/albiFAUz9S2ncUC2j1j/myF17obcnrDWKwMbW0BPIkZmI +qKyKp4GTL+rEkGiZzqcfs5zFIgnbiE4E7r3nKR3uc8RbeJ631che4mZjFi43lt7K +VOAC+OD2j+tCnPz04f8HiUE5uQGNBFcBkmMBDADxUSvSq2B7ctdtq3EyR/msyv0w +zqjE/r/2DAZyodM5Rkz4vSpKL4GWs9dfXFz2g+0snmH95uHTbZ1sV7R0jdD9y0nW ++cz6/eAvZmeDD8fkpaz13T1LiptC0Y1jqpmPUN0tMBCx2ILA/gbogV1N4CG8VB2q +fbbovIF1xUBbw5iT76E77JqrNZ2YxgReaxSfZHjcih0V3k2tshv3CBkFjbwx2WtD +jJ1ZuRMDxMdJzstwKwq2m67Z8eYzvZuJFeBSg6cyXm1lEqLsZg6qSvSa8NWJb2b8 +0/OTQj+Nc+wDptuvgUVpdCTnuhejahzSNUR6JZsndvSnUsKviypOTSHh/4L678WI +sNEFuAv0iYEk+AhpMUIXAll/p0G435bOxkOtWFSbkIkLlvpN0pRF6umn0z1D0Bg6 +XUKeqZmuQ6aof5cP7AT9gj5kTD4Z7BLdXlqvtpJAyMJrWIGSRaXy9QVhkqHU6oXm +UKxosEO8zlcVH8jM9omAG8XOd9+KAqlR/nFQMX8AEQEAAYkDbAQYAQoAIBYhBHGo +EuN0oqgnTRz+ZltcNEJRpdp+BQJXAZJjAhsCAcAJEFtcNEJRpdp+wPQgBBkBCgAd +FiEE4gkjKPkt/ksh70dUtjZz25idcjMFAlcBkmMACgkQtjZz25idcjN7cwv+Kjou +3GApBRTteGLBwJjf5KlrJYo/YRSWqZG6HtR9E++AkOh2/Dl0wL77mwWExzsA0+WI +nsWiq4QxWWmlEZLuJ3shXKzjouRpazW1bXOE+jKXPtcuIX8gWb9ms3V2czQHCX2c +cEN/zo8A5K5LdCB/76weIROkZHb0AO7nME/sz1Ja8QzKOaMDM8xlBt7tMifbqB3j +dy0UmJUeNFttWzPfe1Nv2vTHHhE8WhccoT50bXYs5bPTrvIrtr4ZsfYnUcFxe1cg +a8n5zb2I60YB9akvc4/9Io37QXeHBNFkEMj2ivwpo4j7l9cklno/O5D6FtbIjJFe +PVzxqdcHHKxvb1nF5/BpugHCOO3SxMzukaewFRlBxmsg3tEvoaNviLGsy87skhoK +I0WL3GGASzkkCoMmuG6s3jv23zxYQ55bHLtEiv3e/VWgntWk1jePm97nlLcbkEww +k2tH0skoFQV73/5m3Ys2AaDaUctk+h18o3z0qQRRoEiGlEMkEpCHjBrUGAAL2NwL +/1RDeMNIzMeINdRgTtN1ckzv6rJ3Y9uAV8bcmdY6/9gl5sH6k+Kce0ViF4mBNDW2 +sIlXhtn0ULGpxc3r7XGf6n8VDEtL+pI/vVCoopvKPEWLbYZAF9xHVRiYYUX6ikRX +dXObqJAemErpnEMZq4aXsjQs8n9fnzOI2uut+gum2xu2LRvbiepAbt4kjWkEtZ8U +nj8YNraeB9Dhr5uZ6JqeXc5fOpLiDI7O6250hEWvTX3+rh8055B6b4nI/g8kYCiM +WueITj/0UKe3OeZO9BB/G7UhM83HoMgUHMH+RPcuyWmn/XSR95WYNUgAs1nxi1jq +17cqU9TMSCULhgtds4zJXsbmGUX8+iJAy52gD//BZswDJRJe9YDS5LaMgQgM2XiI +pVyan8lQMzHvxXx638lh7gbzkqM4Zc7TQ8G/KruBvh4Vvt4m0ppZooiF8b9QiqS3 +BD7QblDB8QAGLcLwzAM0uJv33ylHf70U/dLIg7IcBp5NAg6WuvaCfYefn+vNQqD6 +tA== +=nDSP +-----END PGP PUBLIC KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/mail/test/browser/shared-modules/OpenPGPTestUtils.jsm thunderbird-91.8.1+build1/comm/mail/test/browser/shared-modules/OpenPGPTestUtils.jsm --- thunderbird-91.7.0+build2/comm/mail/test/browser/shared-modules/OpenPGPTestUtils.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/test/browser/shared-modules/OpenPGPTestUtils.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -188,7 +188,8 @@ fingerPrintObj, false, [], - isSecret + isSecret, + false ); if (result !== 0) { diff -Nru thunderbird-91.7.0+build2/comm/mail/themes/shared/mail/aboutSupport.css thunderbird-91.8.1+build1/comm/mail/themes/shared/mail/aboutSupport.css --- thunderbird-91.7.0+build2/comm/mail/themes/shared/mail/aboutSupport.css 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mail/themes/shared/mail/aboutSupport.css 2022-04-15 07:49:21.000000000 +0000 @@ -2,6 +2,24 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +@media (-moz-toolbar-prefers-color-scheme: dark) { + :root { + --in-content-button-background: rgba(249, 249, 250, 0.1); + --in-content-button-background-hover: rgba(249, 249, 250, 0.15); + --in-content-button-background-active: rgba(249, 249, 250, 0.2); + --in-content-primary-button-background: #45a1ff; + --in-content-primary-button-background-hover: #65c1ff; + --in-content-primary-button-background-active: #85e1ff; + --in-content-focus-outline-color: #45a1ff; + --in-content-table-header-color: rgb(43, 42, 51); + --in-content-table-header-background: var(--in-content-primary-button-background); + } +} + +th { + border-color: color-mix(in srgb, currentColor 41%, transparent); +} + .data-public { display: none; } @@ -21,12 +39,12 @@ } .thead-level2 > th { - background-color: #ebebeb; - color: #333; + background-color: hsl(0, 0%, 60%); } td.data-private { background-color: #ff9; + color: #333; } .calendar-table > thead > th:nth-of-type(1) { diff -Nru thunderbird-91.7.0+build2/comm/mailnews/addrbook/modules/SQLiteDirectory.jsm thunderbird-91.8.1+build1/comm/mailnews/addrbook/modules/SQLiteDirectory.jsm --- thunderbird-91.7.0+build2/comm/mailnews/addrbook/modules/SQLiteDirectory.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/addrbook/modules/SQLiteDirectory.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -173,6 +173,8 @@ super.init(uri); directories.set(fileName, this); + // Create the DB connection here already, to let init() throw on corrupt SQLite files. + this._dbConnection; } async cleanUp() { await super.cleanUp(); diff -Nru thunderbird-91.7.0+build2/comm/mailnews/addrbook/test/unit/test_collection_2.js thunderbird-91.8.1+build1/comm/mailnews/addrbook/test/unit/test_collection_2.js --- thunderbird-91.7.0+build2/comm/mailnews/addrbook/test/unit/test_collection_2.js 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/addrbook/test/unit/test_collection_2.js 2022-04-15 07:49:21.000000000 +0000 @@ -9,9 +9,10 @@ var nsIAbPMF = Ci.nsIAbPreferMailFormat; function run_test() { - // Test - Get the address collecter + // Test - Get the address collector + loadABFile("data/collect", kPABData.fileName); - // Get the actual collecter + // Get the actual collector var addressCollect = Cc[ "@mozilla.org/addressbook/services/addressCollector;1" ].getService(Ci.nsIAbAddressCollector); @@ -19,10 +20,8 @@ // Set the new pref afterwards to ensure we change correctly Services.prefs.setCharPref("mail.collect_addressbook", kCABData.URI); - loadABFile("data/collect", kPABData.fileName); - // XXX Getting all directories ensures we create all ABs because the - // address collecter can't currently create ABs itself (bug 314448). + // address collector can't currently create ABs itself (bug 314448). MailServices.ab.directories; addressCollect.collectAddress( diff -Nru thunderbird-91.7.0+build2/comm/mailnews/base/src/MailNotificationManager.jsm thunderbird-91.8.1+build1/comm/mailnews/base/src/MailNotificationManager.jsm --- thunderbird-91.7.0+build2/comm/mailnews/base/src/MailNotificationManager.jsm 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/base/src/MailNotificationManager.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -195,16 +195,16 @@ return; } - let numNewMessages = folder.getNumNewMessages(false); - let msgDb = folder.msgDatabase; - let newMsgKeys = msgDb.getNewList().slice(-numNewMessages); - if (newMsgKeys.length == 0) { + let newMsgKeys = this._getNewMsgKeysNotNotified(folder); + let numNewMessages = newMsgKeys.length; + if (!numNewMessages) { return; } + this._logger.debug( `Filling alert info; folder.URI=${folder.URI}, numNewMessages=${numNewMessages}` ); - let firstNewMsgHdr = msgDb.GetMsgHdrForKey(newMsgKeys[0]); + let firstNewMsgHdr = folder.msgDatabase.GetMsgHdrForKey(newMsgKeys[0]); let title = this._getAlertTitle(folder, numNewMessages); let body; @@ -363,6 +363,8 @@ // The use_system_alert pref is false or showAlert somehow failed, use the // customized alert window. this._showCustomizedAlert(folder); + + this._folderBiffTime.set(folder, Date.now()); } /** @@ -372,43 +374,27 @@ * @param {nsIMsgFolder} [folder] - The folder containing new messages. */ _showCustomizedAlert(folder) { - let newMsgKeys; - if (folder) { - // Show this folder or queue it. - newMsgKeys = folder.msgDatabase - .getNewList() - .slice(-folder.getNumNewMessages(false)); - if (this._customizedAlertShown) { - this._pendingFolders.add(folder); - return; - } - } else { + if (this._customizedAlertShown) { + // Queue the folder. + this._pendingFolders.add(folder); + return; + } + if (!folder) { // Get the next folder from the queue. folder = this._pendingFolders.keys().next().value; if (!folder) { return; } - let msgDb = folder.msgDatabase; - let lastBiffTime = this._folderBiffTime.get(folder) || 0; - newMsgKeys = msgDb.getNewList().filter(key => { - // It's possible that after we queued the folder, user has opened the - // folder and read some new messages. We compare the timestamp of each - // NEW message with the last biff time to make sure only real NEW - // messages are alerted. - let msgHdr = msgDb.GetMsgHdrForKey(key); - return msgHdr.dateInSeconds * 1000 > lastBiffTime; - }); - this._pendingFolders.delete(folder); } - if (newMsgKeys.length == 0) { + + let newMsgKeys = this._getNewMsgKeysNotNotified(folder); + if (!newMsgKeys.length) { // No NEW message in the current folder, try the next queued folder. this._showCustomizedAlert(); return; } - this._folderBiffTime.set(folder, Date.now()); - let args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray); args.appendElement(folder); args.appendElement({ @@ -425,6 +411,23 @@ this._customizedAlertShown = true; } + /** + * Get all NEW messages from a folder that we received after last biff time. + * @param {nsIMsgFolder} folder - The message folder to check. + * @returns {number[]} An array of message keys. + */ + _getNewMsgKeysNotNotified(folder) { + let msgDb = folder.msgDatabase; + let lastBiffTime = this._folderBiffTime.get(folder) || 0; + return msgDb + .getNewList() + .slice(-folder.getNumNewMessages(false)) + .filter(key => { + let msgHdr = msgDb.GetMsgHdrForKey(key); + return msgHdr.dateInSeconds * 1000 > lastBiffTime; + }); + } + async _updateUnreadCount() { if (this._updatingUnreadCount) { // _updateUnreadCount can be triggered faster than we finish rendering the diff -Nru thunderbird-91.7.0+build2/comm/mailnews/compose/src/MessageSend.jsm thunderbird-91.8.1+build1/comm/mailnews/compose/src/MessageSend.jsm --- thunderbird-91.7.0+build2/comm/mailnews/compose/src/MessageSend.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/compose/src/MessageSend.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -328,7 +328,11 @@ fail(exitCode, errorMsg) { this._failed = true; let prompt = this.getDefaultPrompt(); - if (!Components.isSuccessCode(exitCode) && prompt) { + if ( + !Components.isSuccessCode(exitCode) && + exitCode != Cr.NS_ERROR_ABORT && + prompt + ) { MsgUtils.sendLogger.error( `Sending failed; ${errorMsg}, exitCode=${exitCode}, originalMsgURI=${this._originalMsgURI}` ); @@ -590,15 +594,15 @@ ); isNSSError = true; } catch (e) { - if (errorName == "sendFailed") { + if (url.errorMessage) { + // url.errorMessage is an already localized message, usually + // combined with the error message from SMTP server. + errorMsg = url.errorMessage; + } else if (errorName != "sendFailed") { // Not the default string. A mailnews error occurred that does not // require the server name to be encoded. Just print the descriptive // string. errorMsg = this._composeBundle.GetStringFromName(errorName); - } else if (url.errorMessage) { - // url.errorMessage is an already localized message, usually - // combined with the error message from SMTP server. - errorMsg = url.errorMessage; } else { errorMsg = this._composeBundle.GetStringFromName( "sendFailedUnexpected" @@ -669,7 +673,6 @@ exitCode = MsgUtils.NS_ERROR_SMTP_SEND_FAILED_REFUSED; break; case Cr.NS_ERROR_NET_INTERRUPT: - case Cr.NS_ERROR_ABORT: exitCode = MsgUtils.NS_ERROR_SMTP_SEND_FAILED_INTERRUPTED; break; case Cr.NS_ERROR_NET_TIMEOUT: diff -Nru thunderbird-91.7.0+build2/comm/mailnews/compose/src/SmtpClient.jsm thunderbird-91.8.1+build1/comm/mailnews/compose/src/SmtpClient.jsm --- thunderbird-91.7.0+build2/comm/mailnews/compose/src/SmtpClient.jsm 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/compose/src/SmtpClient.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -139,6 +139,7 @@ * Sends QUIT */ quit() { + this._authenticating = false; this._sendCommand("QUIT"); this._currentAction = this.close; } @@ -633,7 +634,7 @@ // According to rfc4616#section-2, password should be UTF-8 BinaryString // before base64 encoded. let password = String.fromCharCode( - ...new TextEncoder().encode(this._authenticator.getPassword()) + ...new TextEncoder().encode(this._getPassword()) ); this._sendCommand( @@ -910,7 +911,20 @@ } } - this._authenticateUser(); + if ( + command.data.match(/\bCLIENTID\b/) && + (this._secureTransport || + // For test purpose. + ["localhost", "127.0.0.1", "::1"].includes(this._server.hostname)) && + this._server.clientidEnabled && + this._server.clientid + ) { + // Client identity extension, still a draft. + this._currentAction = this._actionCLIENTID; + this._sendCommand("CLIENTID UUID " + this._server.clientid, true); + } else { + this._authenticateUser(); + } } /** @@ -948,6 +962,39 @@ } /** + * Handles server response for CLIENTID command. If successful then will + * initiate the authenticateUser process. + * + * @param {Object} command Parsed command from the server {statusCode, data} + */ + _actionCLIENTID(command) { + if (!command.success) { + this._onNsError(MsgUtils.NS_ERROR_SMTP_SERVER_ERROR, command.data); + return; + } + this._authenticateUser(); + } + + /** + * Returns the saved/cached server password, or show a password dialog. If the + * user cancels the dialog, abort sending. + * @returns {string} The server password. + */ + _getPassword() { + try { + return this._authenticator.getPassword(); + } catch (e) { + if (e.result == Cr.NS_ERROR_ABORT) { + this.quit(); + this.onerror(e.result); + } else { + throw e; + } + } + return null; + } + + /** * Response to AUTH LOGIN, if successful expects base64 encoded username * * @param {Object} command Parsed command from the server {statusCode, data} @@ -974,7 +1021,7 @@ } this.logger.debug("AUTH LOGIN PASS"); this._currentAction = this._actionAUTHComplete; - let password = this._authenticator.getPassword(); + let password = this._getPassword(); if ( !Services.prefs.getBoolPref( "mail.smtp_login_pop3_user_pass_auth_is_latin1", @@ -1002,7 +1049,7 @@ } // Server sent us a base64 encoded challenge. let challenge = atob(command.data); - let password = this._authenticator.getPassword(); + let password = this._getPassword(); // Use password as key, challenge as payload, generate a HMAC-MD5 signature. let signature = MailCryptoUtils.hmacMd5( new TextEncoder().encode(password), @@ -1097,7 +1144,7 @@ * @param {Object} command Parsed command from the server {statusCode, data} */ _actionIdle(command) { - this._onError(new Error(command.data)); + this._onNsError(MsgUtils.NS_ERROR_SMTP_SERVER_ERROR, command.data); } /** @@ -1247,7 +1294,11 @@ } this._currentAction = this._actionIdle; - this.ondone(command.success ? 0 : MsgUtils.NS_ERROR_SENDING_MESSAGE); + if (command.success) { + this.ondone(0); + } else { + this._onNsError(MsgUtils.NS_ERROR_SENDING_MESSAGE, command.data); + } } // If the client wanted to do something else (eg. to quit), do not force idle diff -Nru thunderbird-91.7.0+build2/comm/mailnews/compose/src/SmtpServer.jsm thunderbird-91.8.1+build1/comm/mailnews/compose/src/SmtpServer.jsm --- thunderbird-91.7.0+build2/comm/mailnews/compose/src/SmtpServer.jsm 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/compose/src/SmtpServer.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -231,6 +231,8 @@ this.username = outUsername.value; } this.password = outPassword.value; + } else { + throw Components.Exception("Password dialog canceled", Cr.NS_ERROR_ABORT); } return this.password; }, diff -Nru thunderbird-91.7.0+build2/comm/mailnews/compose/test/unit/test_smtpClient.js thunderbird-91.8.1+build1/comm/mailnews/compose/test/unit/test_smtpClient.js --- thunderbird-91.7.0+build2/comm/mailnews/compose/test/unit/test_smtpClient.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/compose/test/unit/test_smtpClient.js 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,97 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { PromiseTestUtils } = ChromeUtils.import( + "resource://testing-common/mailnews/PromiseTestUtils.jsm" +); + +let server = setupServerDaemon(); +server.start(); +registerCleanupFunction(() => { + server.stop(); +}); + +/** + * Test sending is aborted when alwaysSTARTTLS is set, but the server doesn't + * support STARTTLS. + */ +add_task(async function testAbort() { + server.resetTest(); + let smtpServer = getBasicSmtpServer(server.port); + let identity = getSmtpIdentity("identity@foo.invalid", smtpServer); + // Set to always use STARTTLS. + smtpServer.socketType = Ci.nsMsgSocketType.alwaysSTARTTLS; + + do_test_pending(); + + let urlListener = { + OnStartRunningUrl(url) {}, + OnStopRunningUrl(url, status) { + // Test sending is aborted with NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS. + Assert.equal(status, 0x80553126); + do_test_finished(); + }, + }; + + // Send a message. + let testFile = do_get_file("data/message1.eml"); + MailServices.smtp.sendMailMessage( + testFile, + "to@foo.invalid", + identity, + "from@foo.invalid", + null, + urlListener, + null, + null, + false, + "", + {}, + {} + ); + server.performTest(); +}); + +/** + * Test client identity extension works. + */ +add_task(async function testClientIdentityExtension() { + server.resetTest(); + let smtpServer = getBasicSmtpServer(server.port); + let identity = getSmtpIdentity("identity@foo.invalid", smtpServer); + // Enable and set clientid to the smtp server. + smtpServer.clientidEnabled = true; + smtpServer.clientid = "uuid-111"; + + // Send a message. + let asyncUrlListener = new PromiseTestUtils.PromiseUrlListener(); + let testFile = do_get_file("data/message1.eml"); + MailServices.smtp.sendMailMessage( + testFile, + "to@foo.invalid", + identity, + "from@foo.invalid", + null, + asyncUrlListener, + null, + null, + false, + "", + {}, + {} + ); + server.performTest(); + + await asyncUrlListener.promise; + + // Check CLIENTID command is sent. + let transaction = server.playTransaction(); + do_check_transaction(transaction, [ + "EHLO test", + "CLIENTID UUID uuid-111", + "MAIL FROM: BODY=8BITMIME SIZE=159", + "RCPT TO:", + "DATA", + ]); +}); diff -Nru thunderbird-91.7.0+build2/comm/mailnews/compose/test/unit/xpcshell-jsm.ini thunderbird-91.8.1+build1/comm/mailnews/compose/test/unit/xpcshell-jsm.ini --- thunderbird-91.7.0+build2/comm/mailnews/compose/test/unit/xpcshell-jsm.ini 2022-03-07 21:35:19.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/compose/test/unit/xpcshell-jsm.ini 2022-04-15 07:49:21.000000000 +0000 @@ -9,5 +9,6 @@ # For some reason this fails with the C++ modules. [test_createAndSendMessage.js] +[test_smtpClient.js] [include:xpcshell-shared.ini] diff -Nru thunderbird-91.7.0+build2/comm/mailnews/mime/src/mimecont.cpp thunderbird-91.8.1+build1/comm/mailnews/mime/src/mimecont.cpp --- thunderbird-91.7.0+build2/comm/mailnews/mime/src/mimecont.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/mime/src/mimecont.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -57,7 +57,24 @@ /* Do this first so that children have their parse_eof methods called in forward order (0-N) but are destroyed in backward order (N-0) */ - if (!object->closed_p) object->clazz->parse_eof(object, false); + + /* If we're being destroyed, prior to deleting any data, mark + * flush data in all childs and mark them as closed, to avoid + * flushing during subsequent mime_free of childs. + * This also helps if this (parent) object is already marked as + * closed, but a child is not yet marked as closed. + */ + ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(object, true); + if (cont->children) { + int i; + for (i = 0; i < cont->nchildren; i++) { + MimeObject* kid = cont->children[i]; + if (kid && !kid->closed_p) { + kid->clazz->parse_eof(kid, true); + } + } + } + if (!object->parsed_p) object->clazz->parse_end(object, false); if (cont->children) { diff -Nru thunderbird-91.7.0+build2/comm/mailnews/mime/src/mimehdrs.cpp thunderbird-91.8.1+build1/comm/mailnews/mime/src/mimehdrs.cpp --- thunderbird-91.7.0+build2/comm/mailnews/mime/src/mimehdrs.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/mime/src/mimehdrs.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -163,10 +163,65 @@ return hdrs2; } +static bool find_header_starts(MimeHeaders* hdrs, bool counting) { + const char* end = hdrs->all_headers + hdrs->all_headers_fp; + char* s = hdrs->all_headers; + int i = 0; + + if (counting) { + // For the start pointer + hdrs->heads_size = 1; + } else { + hdrs->heads[i++] = hdrs->all_headers; + } + + while (s < end) { + SEARCH_NEWLINE: + while (s < end && *s != '\r' && *s != '\n') s++; + + if (s >= end) break; + + /* If "\r\n " or "\r\n\t" is next, that doesn't terminate the header. */ + else if (s + 2 < end && (s[0] == '\r' && s[1] == '\n') && + (s[2] == ' ' || s[2] == '\t')) { + s += 3; + goto SEARCH_NEWLINE; + } + /* If "\r " or "\r\t" or "\n " or "\n\t" is next, that doesn't terminate + the header either. */ + else if (s + 1 < end && (s[0] == '\r' || s[0] == '\n') && + (s[1] == ' ' || s[1] == '\t')) { + s += 2; + goto SEARCH_NEWLINE; + } + + /* At this point, `s' points before a header-terminating newline. + Move past that newline, and store that new position in `heads'. + */ + if (*s == '\r') s++; + + if (s >= end) break; + + if (*s == '\n') s++; + + if (s < end) { + if (counting) { + hdrs->heads_size++; + } else { + NS_ASSERTION(i < hdrs->heads_size, + "1.1 19 Mar 1999 12:00"); + if (i >= hdrs->heads_size) return false; + hdrs->heads[i++] = s; + } + } + } + if (!counting) { + NS_ASSERTION(i == hdrs->heads_size, "unexpected"); + } + return true; +} + int MimeHeaders_build_heads_list(MimeHeaders* hdrs) { - char* s; - char* end; - int i; NS_ASSERTION(hdrs, "1.1 19 Mar 1999 12:00"); if (!hdrs) return -1; @@ -195,68 +250,19 @@ } } - /* First go through and count up the number of headers in the block. - */ - end = hdrs->all_headers + hdrs->all_headers_fp; - for (s = hdrs->all_headers; s < end; s++) { - if (s < (end - 1) && s[0] == '\r' && s[1] == '\n') /* CRLF -> LF */ - s++; - - if ((s[0] == '\r' || s[0] == '\n') && /* we're at a newline, and */ - (s >= (end - 1) || /* we're at EOF, or */ - !(s[1] == ' ' || s[1] == '\t'))) /* next char is nonwhite */ - hdrs->heads_size++; - } + find_header_starts(hdrs, true); /* Now allocate storage for the pointers to each of those headers. */ - hdrs->heads = (char**)PR_MALLOC((hdrs->heads_size + 1) * sizeof(char*)); + hdrs->heads = (char**)PR_MALLOC((hdrs->heads_size) * sizeof(char*)); if (!hdrs->heads) return MIME_OUT_OF_MEMORY; - memset(hdrs->heads, 0, (hdrs->heads_size + 1) * sizeof(char*)); + memset(hdrs->heads, 0, (hdrs->heads_size) * sizeof(char*)); /* Now make another pass through the headers, and this time, record the starting position of each header. */ - - i = 0; - hdrs->heads[i++] = hdrs->all_headers; - s = hdrs->all_headers; - - while (s < end) { - SEARCH_NEWLINE: - while (s < end && *s != '\r' && *s != '\n') s++; - - if (s >= end) break; - - /* If "\r\n " or "\r\n\t" is next, that doesn't terminate the header. */ - else if (s + 2 < end && (s[0] == '\r' && s[1] == '\n') && - (s[2] == ' ' || s[2] == '\t')) { - s += 3; - goto SEARCH_NEWLINE; - } - /* If "\r " or "\r\t" or "\n " or "\n\t" is next, that doesn't terminate - the header either. */ - else if (s + 1 < end && (s[0] == '\r' || s[0] == '\n') && - (s[1] == ' ' || s[1] == '\t')) { - s += 2; - goto SEARCH_NEWLINE; - } - - /* At this point, `s' points before a header-terminating newline. - Move past that newline, and store that new position in `heads'. - */ - if (*s == '\r') s++; - - if (s >= end) break; - - if (*s == '\n') s++; - - if (s < end) { - NS_ASSERTION(!(i > hdrs->heads_size), - "1.1 19 Mar 1999 12:00"); - if (i > hdrs->heads_size) return -1; - hdrs->heads[i++] = s; - } + if (!find_header_starts(hdrs, false)) { + return -1; } return 0; diff -Nru thunderbird-91.7.0+build2/comm/mailnews/mime/src/mimeobj.cpp thunderbird-91.8.1+build1/comm/mailnews/mime/src/mimeobj.cpp --- thunderbird-91.7.0+build2/comm/mailnews/mime/src/mimeobj.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/mime/src/mimeobj.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -235,6 +235,10 @@ } static int MimeObject_parse_eof(MimeObject* obj, bool abort_p) { + if (abort_p) { + obj->closed_p = true; + return 0; + } if (obj->closed_p) return 0; NS_ASSERTION(!obj->parsed_p, "obj already parsed"); @@ -243,7 +247,7 @@ the parse_line method will be called with a string with no trailing newline, which isn't the usual case.) */ - if (!abort_p && obj->ibuffer_fp > 0) { + if (obj->ibuffer_fp > 0) { int status = obj->clazz->parse_line(obj->ibuffer, obj->ibuffer_fp, obj); obj->ibuffer_fp = 0; if (status < 0) { diff -Nru thunderbird-91.7.0+build2/comm/mailnews/mime/src/modlmime.h thunderbird-91.8.1+build1/comm/mailnews/mime/src/modlmime.h --- thunderbird-91.7.0+build2/comm/mailnews/mime/src/modlmime.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/mime/src/modlmime.h 2022-04-15 07:49:21.000000000 +0000 @@ -33,14 +33,15 @@ bool done_p; /* Whether we've read the end-of-headers marker (the terminating blank line.) */ - char** heads; /* An array of length n_headers which points + char** heads; /* An array of length heads_size which points to the beginning of each distinct header: just after the newline which terminated the previous one. This is to speed search. This is not initialized until all the headers have been read. */ - int32_t heads_size; /* The length (and consequently, how many + int32_t heads_size; /* The number of entries (pointers) in the heads + array (and consequently, how many distinct headers are in here.) */ char* obuffer; /* This buffer is used for output. */ diff -Nru thunderbird-91.7.0+build2/comm/mailnews/test/fakeserver/Smtpd.jsm thunderbird-91.8.1+build1/comm/mailnews/test/fakeserver/Smtpd.jsm --- thunderbird-91.7.0+build2/comm/mailnews/test/fakeserver/Smtpd.jsm 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/mailnews/test/fakeserver/Smtpd.jsm 2022-04-15 07:49:21.000000000 +0000 @@ -43,7 +43,7 @@ kUsername: "testsmtp", kPassword: "smtptest", kAuthSchemes: ["CRAM-MD5", "PLAIN", "LOGIN"], - kCapabilities: ["8BITMIME", "SIZE"], + kCapabilities: ["8BITMIME", "SIZE", "CLIENTID"], _nextAuthFunction: undefined, resetTest() { @@ -63,6 +63,9 @@ capa += "\n250 HELP"; // the odd one: no "-", per RFC 2821 return capa; }, + CLIENTID(args) { + return "250 ok"; + }, AUTH(lineRest) { if (this._state == kStateAuthenticated) { return "503 You're already authenticated"; diff -Nru thunderbird-91.7.0+build2/comm/SOURCE_CHANGESET thunderbird-91.8.1+build1/comm/SOURCE_CHANGESET --- thunderbird-91.7.0+build2/comm/SOURCE_CHANGESET 2022-03-07 21:35:21.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/SOURCE_CHANGESET 2022-04-15 07:49:38.000000000 +0000 @@ -1 +1 @@ -39ccd0b9ea033f3292af90667e470b98a79eb8c9 \ No newline at end of file +79f1a34ff6596c36fd01ceee26ae1881cebc4756 \ No newline at end of file diff -Nru thunderbird-91.7.0+build2/comm/taskcluster/scripts/build-libotr.sh thunderbird-91.8.1+build1/comm/taskcluster/scripts/build-libotr.sh --- thunderbird-91.7.0+build2/comm/taskcluster/scripts/build-libotr.sh 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/taskcluster/scripts/build-libotr.sh 2022-04-15 07:49:21.000000000 +0000 @@ -140,7 +140,7 @@ case "${_TARGET_OS}" in win*) cd src - "${CC}" -static-libgcc -shared -Wl,-no-undefined ${LDFLAGS} -o libotr.dll \ + "${CC}" -static-libgcc -s -shared -Wl,-no-undefined ${LDFLAGS} -o libotr.dll \ *.o \ -L"${_PREFIX}/lib" "${_PREFIX}/lib/libgcrypt.a" "${_PREFIX}/lib/libgpg-error.a" \ -L"${_LIBDIR}" -lws2_32 -lssp diff -Nru thunderbird-91.7.0+build2/comm/third_party/botan/botan.mozbuild thunderbird-91.8.1+build1/comm/third_party/botan/botan.mozbuild --- thunderbird-91.7.0+build2/comm/third_party/botan/botan.mozbuild 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/botan/botan.mozbuild 2022-04-15 07:49:21.000000000 +0000 @@ -44,7 +44,7 @@ botan_build = GENERATED_FILES['build/build.h'] botan_build.script = 'botan_configure.py' botan_build.flags = [ - '--cc-bin={}'.format(CONFIG['MZLA_RNP_CXX']), + '--cc-bin={}'.format(CONFIG['CXX']), '--cpu={}'.format(CONFIG['target_cpu']), '--os={}'.format(botan_os), '--with-build-dir={}'.format(OBJDIR), @@ -56,9 +56,6 @@ '--with-cmake', ] - # clock_gettime is not part of OSX until 10.12 sdk, Taskcluster builds with 10.11 - if CONFIG['OS_ARCH'] == 'Darwin': - botan_build.flags.append('--without-os-features=clock_gettime') LOCAL_INCLUDES = ['!build/include'] diff -Nru thunderbird-91.7.0+build2/comm/third_party/bzip2/moz.build thunderbird-91.8.1+build1/comm/third_party/bzip2/moz.build --- thunderbird-91.7.0+build2/comm/third_party/bzip2/moz.build 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/bzip2/moz.build 2022-04-15 07:49:22.000000000 +0000 @@ -13,6 +13,10 @@ else: include("../rnpdefs.mozbuild") + COMPILE_FLAGS["WARNINGS_CFLAGS"] += [ + "-Wno-unreachable-code-return", + ] + SOURCES += [ "blocksort.c", "bzlib.c", diff -Nru thunderbird-91.7.0+build2/comm/third_party/defs.mk thunderbird-91.8.1+build1/comm/third_party/defs.mk --- thunderbird-91.7.0+build2/comm/third_party/defs.mk 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/defs.mk 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# This file is included my mozbuild for this directory and any subdirectories -# that use mozbuild. Currently the OTR libraries do not use mozbuild and -# are not affected. - -# MZLA_RNP_CC and MZLA_RNP_CXX are set in openpgp.configure and are used -# to remove the -std= flags from the commands. -CC := $(MZLA_RNP_CC) -CXX := $(MZLA_RNP_CXX) diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/arraylist.c thunderbird-91.8.1+build1/comm/third_party/json-c/arraylist.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/arraylist.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/arraylist.c 2022-04-15 07:49:21.000000000 +0000 @@ -14,12 +14,12 @@ #include #ifdef STDC_HEADERS -# include -# include +#include +#include #endif /* STDC_HEADERS */ #if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD) -# include +#include #endif /* HAVE_STRINGS_H */ #ifndef SIZE_T_MAX @@ -36,111 +36,166 @@ #include "arraylist.h" -struct array_list* -array_list_new(array_list_free_fn *free_fn) +struct array_list *array_list_new(array_list_free_fn *free_fn) { - struct array_list *arr; + return array_list_new2(free_fn, ARRAY_LIST_DEFAULT_SIZE); +} + +struct array_list *array_list_new2(array_list_free_fn *free_fn, int initial_size) +{ + struct array_list *arr; - arr = (struct array_list*)calloc(1, sizeof(struct array_list)); - if(!arr) return NULL; - arr->size = ARRAY_LIST_DEFAULT_SIZE; - arr->length = 0; - arr->free_fn = free_fn; - if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) { - free(arr); - return NULL; - } - return arr; -} - -extern void -array_list_free(struct array_list *arr) -{ - size_t i; - for(i = 0; i < arr->length; i++) - if(arr->array[i]) arr->free_fn(arr->array[i]); - free(arr->array); - free(arr); + arr = (struct array_list *)malloc(sizeof(struct array_list)); + if (!arr) + return NULL; + arr->size = initial_size; + arr->length = 0; + arr->free_fn = free_fn; + if (!(arr->array = (void **)malloc(arr->size * sizeof(void *)))) + { + free(arr); + return NULL; + } + return arr; } -void* -array_list_get_idx(struct array_list *arr, size_t i) +extern void array_list_free(struct array_list *arr) { - if(i >= arr->length) return NULL; - return arr->array[i]; + size_t i; + for (i = 0; i < arr->length; i++) + if (arr->array[i]) + arr->free_fn(arr->array[i]); + free(arr->array); + free(arr); +} + +void *array_list_get_idx(struct array_list *arr, size_t i) +{ + if (i >= arr->length) + return NULL; + return arr->array[i]; } static int array_list_expand_internal(struct array_list *arr, size_t max) { - void *t; - size_t new_size; + void *t; + size_t new_size; - if(max < arr->size) return 0; - /* Avoid undefined behaviour on size_t overflow */ - if( arr->size >= SIZE_T_MAX / 2 ) - new_size = max; - else - { - new_size = arr->size << 1; - if (new_size < max) - new_size = max; - } - if (new_size > (~((size_t)0)) / sizeof(void*)) return -1; - if (!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1; - arr->array = (void**)t; - (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*)); - arr->size = new_size; - return 0; + if (max < arr->size) + return 0; + /* Avoid undefined behaviour on size_t overflow */ + if (arr->size >= SIZE_T_MAX / 2) + new_size = max; + else + { + new_size = arr->size << 1; + if (new_size < max) + new_size = max; + } + if (new_size > (~((size_t)0)) / sizeof(void *)) + return -1; + if (!(t = realloc(arr->array, new_size * sizeof(void *)))) + return -1; + arr->array = (void **)t; + arr->size = new_size; + return 0; } -int -array_list_put_idx(struct array_list *arr, size_t idx, void *data) +int array_list_shrink(struct array_list *arr, size_t empty_slots) { - if (idx > SIZE_T_MAX - 1 ) return -1; - if(array_list_expand_internal(arr, idx+1)) return -1; - if(idx < arr->length && arr->array[idx]) - arr->free_fn(arr->array[idx]); - arr->array[idx] = data; - if(arr->length <= idx) arr->length = idx + 1; - return 0; + void *t; + size_t new_size; + + new_size = arr->length + empty_slots; + if (new_size == arr->size) + return 0; + if (new_size > arr->size) + return array_list_expand_internal(arr, new_size); + if (new_size == 0) + new_size = 1; + + if (!(t = realloc(arr->array, new_size * sizeof(void *)))) + return -1; + arr->array = (void **)t; + arr->size = new_size; + return 0; +} + +//static inline int _array_list_put_idx(struct array_list *arr, size_t idx, void *data) +int array_list_put_idx(struct array_list *arr, size_t idx, void *data) +{ + if (idx > SIZE_T_MAX - 1) + return -1; + if (array_list_expand_internal(arr, idx + 1)) + return -1; + if (idx < arr->length && arr->array[idx]) + arr->free_fn(arr->array[idx]); + arr->array[idx] = data; + if (idx > arr->length) + { + /* Zero out the arraylist slots in between the old length + and the newly added entry so we know those entries are + empty. + e.g. when setting array[7] in an array that used to be + only 5 elements longs, array[5] and array[6] need to be + set to 0. + */ + memset(arr->array + arr->length, 0, (idx - arr->length) * sizeof(void *)); + } + if (arr->length <= idx) + arr->length = idx + 1; + return 0; } -int -array_list_add(struct array_list *arr, void *data) +int array_list_add(struct array_list *arr, void *data) { - return array_list_put_idx(arr, arr->length, data); + /* Repeat some of array_list_put_idx() so we can skip several + checks that we know are unnecessary when appending at the end + */ + size_t idx = arr->length; + if (idx > SIZE_T_MAX - 1) + return -1; + if (array_list_expand_internal(arr, idx + 1)) + return -1; + arr->array[idx] = data; + arr->length++; + return 0; } -void -array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *)) +void array_list_sort(struct array_list *arr, int (*compar)(const void *, const void *)) { - qsort(arr->array, arr->length, sizeof(arr->array[0]), sort_fn); + qsort(arr->array, arr->length, sizeof(arr->array[0]), compar); } -void* array_list_bsearch(const void **key, struct array_list *arr, - int (*sort_fn)(const void *, const void *)) +void *array_list_bsearch(const void **key, struct array_list *arr, + int (*compar)(const void *, const void *)) { - return bsearch(key, arr->array, arr->length, sizeof(arr->array[0]), - sort_fn); + return bsearch(key, arr->array, arr->length, sizeof(arr->array[0]), compar); } -size_t -array_list_length(struct array_list *arr) +size_t array_list_length(struct array_list *arr) { - return arr->length; + return arr->length; } -int -array_list_del_idx( struct array_list *arr, size_t idx, size_t count ) +int array_list_del_idx(struct array_list *arr, size_t idx, size_t count) { size_t i, stop; + /* Avoid overflow in calculation with large indices. */ + if (idx > SIZE_T_MAX - count) + return -1; stop = idx + count; - if ( idx >= arr->length || stop > arr->length ) return -1; - for ( i = idx; i < stop; ++i ) { - if ( arr->array[i] ) arr->free_fn( arr->array[i] ); + if (idx >= arr->length || stop > arr->length) + return -1; + for (i = idx; i < stop; ++i) + { + // Because put_idx can skip entries, we need to check if + // there's actually anything in each slot we're erasing. + if (arr->array[i]) + arr->free_fn(arr->array[i]); } - memmove( arr->array + idx, arr->array + stop, (arr->length - stop) * sizeof(void*) ); + memmove(arr->array + idx, arr->array + stop, (arr->length - stop) * sizeof(void *)); arr->length -= count; return 0; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/arraylist.h thunderbird-91.8.1+build1/comm/third_party/json-c/arraylist.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/arraylist.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/arraylist.h 2022-04-15 07:49:22.000000000 +0000 @@ -22,46 +22,64 @@ extern "C" { #endif +#include + #define ARRAY_LIST_DEFAULT_SIZE 32 -typedef void (array_list_free_fn) (void *data); +typedef void(array_list_free_fn)(void *data); struct array_list { - void **array; - size_t length; - size_t size; - array_list_free_fn *free_fn; + void **array; + size_t length; + size_t size; + array_list_free_fn *free_fn; }; typedef struct array_list array_list; -extern struct array_list* -array_list_new(array_list_free_fn *free_fn); - -extern void -array_list_free(struct array_list *al); - -extern void* -array_list_get_idx(struct array_list *al, size_t i); - -extern int -array_list_put_idx(struct array_list *al, size_t i, void *data); - -extern int -array_list_add(struct array_list *al, void *data); - -extern size_t -array_list_length(struct array_list *al); - -extern void -array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *)); - -extern void* array_list_bsearch(const void **key, - struct array_list *arr, - int (*sort_fn)(const void *, const void *)); - -extern int -array_list_del_idx(struct array_list *arr, size_t idx, size_t count); +/** + * Allocate an array_list of the default size (32). + * @deprecated Use array_list_new2() instead. + */ +extern struct array_list *array_list_new(array_list_free_fn *free_fn); + +/** + * Allocate an array_list of the desired size. + * + * If possible, the size should be chosen to closely match + * the actual number of elements expected to be used. + * If the exact size is unknown, there are tradeoffs to be made: + * - too small - the array_list code will need to call realloc() more + * often (which might incur an additional memory copy). + * - too large - will waste memory, but that can be mitigated + * by calling array_list_shrink() once the final size is known. + * + * @see array_list_shrink + */ +extern struct array_list *array_list_new2(array_list_free_fn *free_fn, int initial_size); + +extern void array_list_free(struct array_list *al); + +extern void *array_list_get_idx(struct array_list *al, size_t i); + +extern int array_list_put_idx(struct array_list *al, size_t i, void *data); + +extern int array_list_add(struct array_list *al, void *data); + +extern size_t array_list_length(struct array_list *al); + +extern void array_list_sort(struct array_list *arr, int (*compar)(const void *, const void *)); + +extern void *array_list_bsearch(const void **key, struct array_list *arr, + int (*compar)(const void *, const void *)); + +extern int array_list_del_idx(struct array_list *arr, size_t idx, size_t count); + +/** + * Shrink the array list to just enough to fit the number of elements in it, + * plus empty_slots. + */ +extern int array_list_shrink(struct array_list *arr, size_t empty_slots); #ifdef __cplusplus } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/AUTHORS thunderbird-91.8.1+build1/comm/third_party/json-c/AUTHORS --- thunderbird-91.7.0+build2/comm/third_party/json-c/AUTHORS 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/AUTHORS 2022-04-15 07:49:21.000000000 +0000 @@ -1,5 +1,30 @@ -Michael Clark -Jehiah Czebotar -Eric Haszlakiewicz +Alexander Dahl +andy5995 +Björn Esser +changyong guo +chenguoping +Christopher Head +Chris Wolfe C. Watford (christopher.watford@gmail.com) - +Darjan Krijan +Eric Hawicz +grdowns +Ivan Romanov +Jaap Keuter +janczer +Jehan +Jehiah Czebotar +Jonathan Wiens +Jose Bollo +Keith Holman +Liang, Gao +max +Michael Clark +myd7349 +Pierce Lopez +Po-Chuan Hsieh +Ramiro Polla +Rikard Falkeborn +Robert +Rubasri Kalidas +Unmanned Player <36690541+unmanned-player@users.noreply.github.com> diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/bits.h thunderbird-91.8.1+build1/comm/third_party/json-c/bits.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/bits.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/bits.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -/** - * @file - * @brief Do not use, only contains deprecated defines. - * @deprecated Use json_util.h instead. - * - * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _bits_h_ -#define _bits_h_ - -/** - * @deprecated - */ -#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) -/** - * @deprecated - */ -#define error_ptr(error) ((void*)error) -/** - * @deprecated - */ -#define error_description(error) (json_tokener_get_error(error)) -/** - * @deprecated - */ -#define is_error(ptr) (ptr == NULL) - -#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/ChangeLog thunderbird-91.8.1+build1/comm/third_party/json-c/ChangeLog --- thunderbird-91.7.0+build2/comm/third_party/json-c/ChangeLog 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/ChangeLog 2022-04-15 07:49:21.000000000 +0000 @@ -1,8 +1,154 @@ +Next Release 0.15 +===================== + +Deprecated and removed features: +-------------------------------- +* Deprecate `array_list_new()` in favor of `array_list_new2()` +* Remove the THIS_FUNCTION_IS_DEPRECATED define. +* Remove config.h.win32 + +New features +------------ +* Add a `JSON_TOKENER_ALLOW_TRAILING_CHARS` flag to allow multiple objects + to be parsed even when `JSON_TOKENER_STRICT` is set. +* Add `json_object_new_array_ext(int)` and `array_list_new_2(int)` to allow + arrays to be allocated with the exact size needed, when known. +* Add `json_object_array_shrink()` (and `array_list_shrink()`) and use it in + json_tokener to minimize the amount of memory used. +* Add a json_parse binary, for use in testing changes (not installed, but + available in the apps directory). + +Build changes +------------- +* #639/#621 - Add symbol versions to all exported symbols +* #508/#634 - Always enable -fPIC to allow use of the json-c static library in + other libraries +* Build both static and shared libraries at the same time. +* #626 - Restore compatibility with cmake 2.8 +* #471 - Always create directories with mode 0755, regardless of umask. +* #606/#604 - Improve support for OSes like AIX and IBM i, as well as for + MINGW32 and old versions of MSVC +* #451/#617 - Add a DISABLE_THREAD_LOCAL_STORAGE cmake option to disable + the use of thread-local storage. + +Significant changes and bug fixes +--------------------------------- +* Split the internal json_object structure into several sub-types, one for + each json_type (json_object_object, json_object_string, etc...). + This improves memory usage and speed, with the benchmark under + bench/ report 5.8% faster test time and 6%(max RSS)-12%(peak heap) + less memory usage. + Memory used just for json_object structures decreased 27%, so use cases + with fewer arrays and/or strings would benefit more. +* Minimize memory usage in array handling in json_tokener by shrinking + arrays to the exact number of elements parsed. On bench/ benchmark: + 9% faster test time, 39%(max RSS)-50%(peak heap) less memory usage. + Add json_object_array_shrink() and array_list_shrink() functions. +* #616 - Parsing of surrogate pairs in unicode escapes now properly handles + incremental parsing. +* Fix incremental parsing of numbers, especially those with exponents, e.g. + so parsing "[0", "e+", "-]" now properly returns an error. + Strict mode now rejects missing exponents ("0e"). +* Successfully return number objects at the top level even when they are + followed by a "-", "." or "e". This makes parsing things like "123-45" + behave consistently with things like "123xyz". + +Other changes +------------- +* #589 - Detect broken RDRAND during initialization; also, fix segfault + in the CPUID check. +* #592 - Fix integer overflows to prevert out of bounds write on large input. +* Protect against division by zero in linkhash, when creaed with zero size. +* #602 - Fix json_parse_uint64() internal error checking, leaving the retval + untouched in more failure cases. +* #614 - Prevent truncation when custom double formatters insert extra \0's + + +*** + +0.14 (up to commit 9ed00a6, 2020/04/14) +========================================= + +Deprecated and removed features: +-------------------------------- +* bits.h has been removed +* lh_abort() has been removed +* lh_table_lookup() has been removed, use lh_table_lookup_ex() instead. +* Remove TRUE and FALSE defines, use 1 and 0 instead. + +Build changes: +-------------- +## Deprecated and removed features: +* bits.h has been removed +* lh_abort() has been removed +* lh_table_lookup() has been removed, use lh_table_lookup_ex() instead. +* Remove TRUE and FALSE defines, use 1 and 0 instead. +* autoconf support, including autogen.sh, has been removed. See details about cmake, below. +* With the addition of json_tokener_get_parse_end(), access to internal fields of json_tokener, as well as use of many other symbols and types in json_tokener.h, is deprecated now. +* The use of Android.configure.mk to build for Android no longer works, and it is unknown how (or if) the new cmake-based build machinery can be used. + * Reports of success, or pull requests to correct issues are welcome. + +## Notable improvements and new features + +### Builds and documentation +* Build machinery has been switched to CMake. See README.md for details about how to build. + * TL;DR: `mkdir build ; cd build ; cmake -DCMAKE_INSTALL_PREFIX=/some/path ../json-c ; make all test install` + * To ease the transition, there is a `cmake-configure` wrapper that emulates the old autoconf-based configure script. + * This has enabled improvements to the build on Windows system; also all public functions have been fixed to be properly exported. For best results, use Visual Studio 2015 or newer. +* The json-c style guide has been updated to specify the use of clang-format, and all code has been reformatted. + * Since many lines of code have trivial changes now, when using git blame, be sure to specify -w +* Numerous improvements have been made to the documentation including function effects on refcounts, when passing a NULL is safe, and so on. + +### json_tokener changes +* Added a json_tokener_get_parse_end() function to replace direct access of tok->char_offset. + * The char_offset field, and the rest of the json_tokener structure remain exposed for now, but expect a future release to hide it like is done with json_object_private.h +* json_tokener_parse_ex() now accepts a new JSON_TOKENER_VALIDATE_UTF8 flag to validate that input is UTF8. + * If validation fails, json_tokener_get_error(tok) will return json_tokener_error_parse_utf8_string (see enum json_tokener_error). + +### Other changes and additions +* Add support for unsigned 64-bit integers, uint64_t, to gain one extra bit of magnitude for positive ints. + * json_tokener will now parse values up to UINT64_MAX (18446744073709551615) + * Existing methods returning int32_t or int64_t will cap out-of-range values at INT32_MAX or INT64_MAX, preserving existing behavior. + * The implementation includes the possibility of easily extending this to larger sizes in the future. +* A total of 7 new functions were added: + * json_object_get_uint64 ( struct json_object const* jso ) + * json_object_new_uint64 ( uint64_t i ) + * json_object_set_uint64 ( struct json_object* jso, uint64_t new_value ) + * json_parse_uint64 ( char const* buf, uint64_t* retval ) + * See description of uint64 support, above. + * json_tokener_get_parse_end ( struct json_tokener* tok ) + * See details under "json_tokener changes", above. + * json_object_from_fd_ex ( int fd, int in_depth ) + * Allows the max nesting depth to be specified. + * json_object_new_null ( ) + * Simply returns NULL. Its use is not recommended. +* The size of struct json_object has decreased from 96 bytes to 88 bytes. + +### Testing +* Many updates were made to test cases, increasing code coverage. +* There is now a quick way (JSONC_TEST_TRACE=1) to turn on shell tracing in tests. +* To run tests, use `make test`; the old "check" target no longer exists. + +## Significant bug fixes +For the full list of issues and pull requests since the previous release, please see issues_closed_for_0.14.md + +* [Issue #389](https://github.com/json-c/json-c/issues/389): Add an assert to explicitly crash when _ref_count is corrupted, instead of a later "double free" error. +* [Issue #407](https://github.com/json-c/json-c/issues/407): fix incorrect casts in calls to ctype functions (isdigit and isspace) so we don't crash when asserts are enabled on certain platforms and characters > 128 are parsed. +* [Issue #418](https://github.com/json-c/json-c/issues/418): Fix docs for json_util_from_fd and json_util_from_file to say that they return NULL on failures. +* [Issue #422](https://github.com/json-c/json-c/issues/422): json_object.c:set errno in json_object_get_double() when called on a json_type_string object with bad content. +* [Issue #453](https://github.com/json-c/json-c/issues/453): Fixed misalignment in JSON serialization when JSON_C_TO_STRING_SPACED and JSON_C_TO_STRING_PRETTY are used together. +* [Issue #463](https://github.com/json-c/json-c/issues/463): fix newlocale() call to use LC_NUMERIC_MASK instead of LC_NUMERIC, and remove incorrect comment. +* [Issue #486](https://github.com/json-c/json-c/issues/486): append a missing ".0" to negative double values to ensure they are serialized as floating point numbers. +* [Issue #488](https://github.com/json-c/json-c/issues/488): use JSON_EXPORT on functions so they are properly exported on Windows. +* [Issue #539](https://github.com/json-c/json-c/issues/539): use an internal-only serializer function in json_object_new_double_s() to avoid potential conflicts with user code that uses the json_object_userdata_to_json_string serializer. + +*** + 0.13.1 (up to commit 0f814e5, 2018/03/04) ========================================= -* Bump the major version of the .so library generated up to 4.0 to avoid +* Bump the major version of the .so library generated up to 4.0 to avoid conflicts because some downstream packagers of json-c had already done their own bump to ".so.3" for a much older 0.12 release. * Add const size_t json_c_object_sizeof() @@ -12,6 +158,7 @@ * Issue #396: fix build for certain uClibc based systems. * Add a top level fuzz directory for fuzzers run by OSS-Fuzz + 0.13 (up to commit 5dae561, 2017/11/29) ================================= @@ -26,7 +173,7 @@ Deprecated and removed features: -------------------------------- * All internal use of bits.h has been eliminated. The file will be removed. - Do not use: hexdigit(), error_ptr(), error_descrition() and it_error() + Do not use: hexdigit(), error_ptr(), error_descrition() and it_error() * lh_abort() is deprecated. It will be removed. Behavior changes: @@ -169,11 +316,11 @@ * Make the json_tokener_errors array local. It has been deprecated for a while, and json_tokener_error_desc() should be used instead. - * change the floating point output format to %.17g so values with + * change the floating point output format to %.17g so values with more than 6 digits show up in the output. * Remove the old libjson.so name compatibility support. The library is - only created as libjson-c.so now and headers are only installed + only created as libjson-c.so now and headers are only installed into the ${prefix}/json-c directory. * When supported by the linker, add the -Bsymbolic-functions flag. @@ -239,7 +386,7 @@ * Allow json_tokener_parse_ex() to be re-used to parse multiple object. Also, fix some parsing issues with capitalized hexadecimal numbers and number in E notation. - * Add json_tokener_get_error() and json_tokener_error_desc() to better + * Add json_tokener_get_error() and json_tokener_error_desc() to better encapsulate the process of retrieving errors while parsing. * Various improvements to the documentation of many functions. * Add new json_object_array_sort() function. @@ -286,7 +433,7 @@ Brent Miller, bdmiller at yahoo dash inc dot com * Disable REFCOUNT_DEBUG by default in json_object.c * Don't use this as a variable, so we can compile with a C++ compiler - * Add casts from void* to type of assignment when using malloc + * Add casts from void* to type of assignment when using malloc * Add #ifdef __cplusplus guards to all of the headers * Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table Michael Clark, @@ -322,7 +469,7 @@ 0.6 === * Fix bug in escaping of control characters - Johan Bjrklund, johbjo09 at kth dot se + Johan Björklund, johbjo09 at kth dot se * Remove include "config.h" from headers (should only be included from .c files) Michael Clark @@ -370,13 +517,13 @@ Added a Win32/Win64 compliant implementation of strndup * json_util.c - C. Watford (christopher.watford@gmail.com) Added cast and mask to suffice size_t v. unsigned int conversion - correctness + correctness * json_tokener.c - sign reversal issue on error info for nested object parse - spotted by Johan Bjrklund (johbjo09 at kth.se) + spotted by Johan Björklund (johbjo09 at kth.se) * json_object.c - escape " in json_escape_str * Change to automake and libtool to build shared and static library Michael Clark - + 0.1 === * initial release diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/config.h.in thunderbird-91.8.1+build1/comm/third_party/json-c/config.h.in --- thunderbird-91.7.0+build2/comm/third_party/json-c/config.h.in 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/config.h.in 2022-04-15 07:49:21.000000000 +0000 @@ -1,46 +1,20 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ +/* config.h.in. Modified for moz.build from cmake/config.h.in. */ /* Enable RDRAND Hardware RNG Hash Seed */ #undef ENABLE_RDRAND +/* Override json_c_get_random_seed() with custom code */ +#undef OVERRIDE_GET_RANDOM_SEED + /* Enable partial threading support */ #undef ENABLE_THREADING /* Define if .gnu.warning accepts long strings. */ #undef HAS_GNU_WARNING_LONG -/* Has atomic builtins */ -#undef HAVE_ATOMIC_BUILTINS - -/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you - don't. */ -#undef HAVE_DECL_INFINITY - -/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. - */ -#undef HAVE_DECL_ISINF - -/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. - */ -#undef HAVE_DECL_ISNAN - -/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */ -#undef HAVE_DECL_NAN - -/* Define to 1 if you have the declaration of `_finite', and to 0 if you - don't. */ -#undef HAVE_DECL__FINITE - -/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't. - */ -#undef HAVE_DECL__ISNAN - /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -#undef HAVE_DOPRNT - /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H @@ -59,18 +33,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H -/* Define to 1 if you have the `open' function. */ -#undef HAVE_OPEN - -/* Define to 1 if you have the `realloc' function. */ -#undef HAVE_REALLOC - -/* Define to 1 if you have the `setlocale' function. */ -#undef HAVE_SETLOCALE - -/* Define to 1 if you have the `snprintf' function. */ -#undef HAVE_SNPRINTF - /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H @@ -80,24 +42,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H -/* Define to 1 if you have the `strcasecmp' function. */ -#undef HAVE_STRCASECMP - -/* Define to 1 if you have the `strdup' function. */ -#undef HAVE_STRDUP - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the `strncasecmp' function. */ -#undef HAVE_STRNCASECMP - /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H @@ -107,6 +57,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H @@ -116,6 +69,63 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the header file. */ +#undef HAVE_XLOCALE_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Has atomic builtins */ +#undef HAVE_ATOMIC_BUILTINS + +/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you + don't. */ +#undef HAVE_DECL_INFINITY + +/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. + */ +#undef HAVE_DECL_ISINF + +/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. + */ +#undef HAVE_DECL_ISNAN + +/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */ +#undef HAVE_DECL_NAN + +/* Define to 1 if you have the declaration of `_finite', and to 0 if you + don't. */ +#undef HAVE_DECL__FINITE + +/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't. + */ +#undef HAVE_DECL__ISNAN + +/* Define to 1 if you have the `open' function. */ +#undef HAVE_OPEN + +/* Define to 1 if you have the `realloc' function. */ +#undef HAVE_REALLOC + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `strncasecmp' function. */ +#undef HAVE_STRNCASECMP + /* Define to 1 if you have the `uselocale' function. */ #undef HAVE_USELOCALE @@ -131,8 +141,8 @@ /* Define to 1 if you have the `vsyslog' function. */ #undef HAVE_VSYSLOG -/* Define to 1 if you have the header file. */ -#undef HAVE_XLOCALE_H +/* Define if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE /* Have __thread */ #undef HAVE___THREAD @@ -140,10 +150,6 @@ /* Public define for json_inttypes.h */ #undef JSON_C_HAVE_INTTYPES_H -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - /* Name of package */ #undef PACKAGE @@ -180,6 +186,9 @@ /* The number of bytes in type size_t */ #undef SIZEOF_SIZE_T +/* The number of bytes in type ssize_t */ +#undef SIZEOF_SSIZE_T + /* Specifier for __thread */ #undef SPEC___THREAD diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/config.h.win32 thunderbird-91.8.1+build1/comm/third_party/json-c/config.h.win32 --- thunderbird-91.7.0+build2/comm/third_party/json-c/config.h.win32 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/config.h.win32 1970-01-01 00:00:00.000000000 +0000 @@ -1,205 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Enable RDRANR Hardware RNG Hash Seed */ -#undef ENABLE_RDRAND - -/* Define if .gnu.warning accepts long strings. */ -#undef HAS_GNU_WARNING_LONG - -/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you - don't. */ -#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__) -#define HAVE_DECL_INFINITY 1 -#endif - -/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. - */ -#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__) -#define HAVE_DECL_ISINF 1 -#endif - -/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. - */ -#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__) -#define HAVE_DECL_ISNAN 1 -#endif - -/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */ -#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__) -#define HAVE_DECL_NAN 1 -#endif - -/* Define to 1 if you have the declaration of `_finite', and to 0 if you - don't. */ -#define HAVE_DECL__FINITE 1 - -/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't. - */ -#define HAVE_DECL__ISNAN 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -#define HAVE_DOPRNT 1 - -/* Define to 1 if you have the header file. */ -#undef HAVE_ENDIAN_H - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `open' function. */ -#define HAVE_OPEN 1 - -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#define HAVE_REALLOC 1 - -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - -/* Define to 1 if you have the `snprintf' function. */ -#if defined(__MINGW32__) -#define HAVE_SNPRINTF 1 -#else -#undef HAVE_SNPRINTF -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcasecmp' function. */ -#define HAVE_STRCASECMP 1 - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 0 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strncasecmp' function. */ -#if defined(__MINGW32__) -#define HAVE_STRNCASECMP 1 -#else -#undef HAVE_STRNCASECMP -#endif - -#cmakedefine HAVE_STRTOLL -#cmakedefine strtoll @cmake_strtoll@ - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_CDEFS_H 1 - -/* Define to 1 if you have the header file. */ -#if defined(__MINGW32__) -#define HAVE_SYS_PARAM_H 1 -#else -#undef HAVE_SYS_PARAM_H -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#if defined(__MINGW32__) -#define HAVE_UNISTD_H 1 -#else -#undef HAVE_UNISTD_H -#endif - -/* Define to 1 if you have the `vasprintf' function. */ -#if defined(__MINGW32__) -#define HAVE_VASPRINTF 1 -#else -#undef HAVE_VASPRINTF -#endif - -/* Define to 1 if you have the `vprintf' function. */ -#define HAVE_VPRINTF 1 - -/* Define to 1 if you have the `vsnprintf' function. */ -#define HAVE_VSNPRINTF 1 - -/* Define to 1 if you have the `vsyslog' function. */ -#undef HAVE_VSYSLOG - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - -/* Name of package */ -#define PACKAGE "json-c" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "json-c@googlegroups.com" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "JSON C Library" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "JSON C Library 0.13.1" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "json-c" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "https://github.com/json-c/json-c" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.13.1" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "0.13.1" - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to rpl_malloc if the replacement function should be used. */ -/* #undef malloc */ - -/* Define to rpl_realloc if the replacement function should be used. */ -/* #undef realloc */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/debug.c thunderbird-91.8.1+build1/comm/third_party/json-c/debug.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/debug.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/debug.c 2022-04-15 07:49:21.000000000 +0000 @@ -11,17 +11,17 @@ #include "config.h" +#include #include #include #include -#include #if HAVE_SYSLOG_H -# include +#include #endif /* HAVE_SYSLOG_H */ #if HAVE_UNISTD_H -# include +#include #endif /* HAVE_UNISTD_H */ #if HAVE_SYS_PARAM_H @@ -33,51 +33,64 @@ static int _syslog = 0; static int _debug = 0; -void mc_set_debug(int debug) { _debug = debug; } -int mc_get_debug(void) { return _debug; } +void mc_set_debug(int debug) +{ + _debug = debug; +} +int mc_get_debug(void) +{ + return _debug; +} extern void mc_set_syslog(int syslog) { - _syslog = syslog; + _syslog = syslog; } void mc_debug(const char *msg, ...) { - va_list ap; - if(_debug) { - va_start(ap, msg); + va_list ap; + if (_debug) + { + va_start(ap, msg); #if HAVE_VSYSLOG - if(_syslog) { - vsyslog(LOG_DEBUG, msg, ap); - } else + if (_syslog) + { + vsyslog(LOG_DEBUG, msg, ap); + } + else #endif - vprintf(msg, ap); - va_end(ap); - } + vprintf(msg, ap); + va_end(ap); + } } void mc_error(const char *msg, ...) { - va_list ap; - va_start(ap, msg); + va_list ap; + va_start(ap, msg); #if HAVE_VSYSLOG - if(_syslog) { + if (_syslog) + { vsyslog(LOG_ERR, msg, ap); - } else + } + else #endif vfprintf(stderr, msg, ap); - va_end(ap); + va_end(ap); } void mc_info(const char *msg, ...) { - va_list ap; - va_start(ap, msg); + va_list ap; + va_start(ap, msg); #if HAVE_VSYSLOG - if(_syslog) { + if (_syslog) + { vsyslog(LOG_INFO, msg, ap); - } else + } + else #endif vfprintf(stderr, msg, ap); - va_end(ap); + va_end(ap); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/debug.h thunderbird-91.8.1+build1/comm/third_party/json-c/debug.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/debug.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/debug.h 2022-04-15 07:49:21.000000000 +0000 @@ -23,14 +23,22 @@ extern "C" { #endif -extern void mc_set_debug(int debug); -extern int mc_get_debug(void); +#ifndef JSON_EXPORT +#if defined(_MSC_VER) +#define JSON_EXPORT __declspec(dllexport) +#else +#define JSON_EXPORT extern +#endif +#endif + +JSON_EXPORT void mc_set_debug(int debug); +JSON_EXPORT int mc_get_debug(void); -extern void mc_set_syslog(int syslog); +JSON_EXPORT void mc_set_syslog(int syslog); -extern void mc_debug(const char *msg, ...); -extern void mc_error(const char *msg, ...); -extern void mc_info(const char *msg, ...); +JSON_EXPORT void mc_debug(const char *msg, ...); +JSON_EXPORT void mc_error(const char *msg, ...); +JSON_EXPORT void mc_info(const char *msg, ...); #ifndef __STRING #define __STRING(x) #x @@ -38,17 +46,24 @@ #ifndef PARSER_BROKEN_FIXED -#define JASSERT(cond) do {} while(0) +#define JASSERT(cond) \ + do \ + { \ + } while (0) #else -#define JASSERT(cond) do { \ - if (!(cond)) { \ - mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \ - *(int *)0 = 1;\ - abort(); \ - }\ - } while(0) +#define JASSERT(cond) \ + do \ + { \ + if (!(cond)) \ + { \ + mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", \ + __FILE__, __LINE__); \ + *(int *)0 = 1; \ + abort(); \ + } \ + } while (0) #endif @@ -61,11 +76,19 @@ #define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__) #define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__) #else -#define MC_SET_DEBUG(x) if (0) mc_set_debug(x) +#define MC_SET_DEBUG(x) \ + if (0) \ + mc_set_debug(x) #define MC_GET_DEBUG() (0) -#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x) -#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__) -#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__) +#define MC_SET_SYSLOG(x) \ + if (0) \ + mc_set_syslog(x) +#define MC_DEBUG(x, ...) \ + if (0) \ + mc_debug(x, ##__VA_ARGS__) +#define MC_INFO(x, ...) \ + if (0) \ + mc_info(x, ##__VA_ARGS__) #endif #ifdef __cplusplus diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/INSTALL thunderbird-91.8.1+build1/comm/third_party/json-c/INSTALL --- thunderbird-91.7.0+build2/comm/third_party/json-c/INSTALL 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/INSTALL 2022-04-15 07:49:21.000000000 +0000 @@ -1,3 +1,2 @@ See README.md for installation instructions. - diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/issues_closed_for_0.13.md thunderbird-91.8.1+build1/comm/third_party/json-c/issues_closed_for_0.13.md --- thunderbird-91.7.0+build2/comm/third_party/json-c/issues_closed_for_0.13.md 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/issues_closed_for_0.13.md 2022-04-15 07:49:21.000000000 +0000 @@ -1,267 +1,270 @@ This list was created with: +``` curl https://api.github.com/search/issues?q="repo%3Ajson-c%2Fjson-c+closed%3A>2014-04-10+created%3A<2017-12-01&sort=created&order=asc&per_page=400&page=1" > issues1.out curl https://api.github.com/search/issues?q="repo%3Ajson-c%2Fjson-c+closed%3A>2014-04-10+created%3A<2017-12-01&sort=created&order=asc&per_page=400&page=2" > issues2.out curl https://api.github.com/search/issues?q="repo%3Ajson-c%2Fjson-c+closed%3A>2014-04-10+created%3A<2017-12-01&sort=created&order=asc&per_page=400&page=3" > issues3.out jq -r '.items[] | "[" + .title + "](" + .url + ")" | tostring' issues?.out > issues.md +sed -e's,^\[ *\(.*\)\](https://api.github.com/.*/\([0-9].*\)),[Issue #\2](https://github.com/json-c/json-c/issues/\2) - \1,' -i issues.md #... manual editing ... +``` ---- Issues and Pull Requests closed for the 0.13 release (since commit f84d9c, the 0.12 branch point, 2014-04-10) -[Make json_object_object_add() indicate success or failure, test fix](https://api.github.com/repos/json-c/json-c/issues/61) -[Build fixes (make dist and make distcheck)](https://api.github.com/repos/json-c/json-c/issues/113) -[Fixing build](https://api.github.com/repos/json-c/json-c/issues/124) -[Fix compile error(variable size set but not used) on g++4.6](https://api.github.com/repos/json-c/json-c/issues/125) -[Removed unused size variable.](https://api.github.com/repos/json-c/json-c/issues/126) -[remove unused `size` variable](https://api.github.com/repos/json-c/json-c/issues/127) -[Remove unused variable from json_tokenizer.c](https://api.github.com/repos/json-c/json-c/issues/128) -[Failed to compile under Ubuntu 13.10 32bit](https://api.github.com/repos/json-c/json-c/issues/130) -[undefined symbol: __sync_val_compare_and_swap_4 ](https://api.github.com/repos/json-c/json-c/issues/131) -[Remove unused variable 'size'](https://api.github.com/repos/json-c/json-c/issues/132) -[Update and rename README to README.md](https://api.github.com/repos/json-c/json-c/issues/133) -[Must remove variable size...](https://api.github.com/repos/json-c/json-c/issues/134) -[bits.h uses removed json_tokener_errors\[error\]](https://api.github.com/repos/json-c/json-c/issues/135) -[Error when running make check](https://api.github.com/repos/json-c/json-c/issues/136) -[config.h.in should not be in git](https://api.github.com/repos/json-c/json-c/issues/137) -[Can't build on RHEL 6.5 due to dependency on automake-1.14](https://api.github.com/repos/json-c/json-c/issues/138) -[Code bug in random_test.c evaluating same expression twice ](https://api.github.com/repos/json-c/json-c/issues/140) -[Removed duplicate check in random_seed test - bug #140](https://api.github.com/repos/json-c/json-c/issues/141) -[Please undeprecate json_object_object_get](https://api.github.com/repos/json-c/json-c/issues/142) -[Introduce json_object_from_fd](https://api.github.com/repos/json-c/json-c/issues/144) -[Handle % character properly](https://api.github.com/repos/json-c/json-c/issues/145) -[TAGS rename](https://api.github.com/repos/json-c/json-c/issues/146) -[Bump the soname](https://api.github.com/repos/json-c/json-c/issues/148) -[SONAME bump](https://api.github.com/repos/json-c/json-c/issues/149) -[Fix build using MinGW.](https://api.github.com/repos/json-c/json-c/issues/150) -[Remove json_type enum trailing comma](https://api.github.com/repos/json-c/json-c/issues/151) -[error while compiling json-c library version 0.11](https://api.github.com/repos/json-c/json-c/issues/152) -[improve doc for json_object_to_json_string()](https://api.github.com/repos/json-c/json-c/issues/153) -[double precision](https://api.github.com/repos/json-c/json-c/issues/154) -[add bsearch for arrays](https://api.github.com/repos/json-c/json-c/issues/155) -[Remove trailing whitespaces](https://api.github.com/repos/json-c/json-c/issues/156) -[JSON-C shall not exit on calloc fail.](https://api.github.com/repos/json-c/json-c/issues/157) -[while using json-c 0.11, I am facing strange crash issue in json_object_put.](https://api.github.com/repos/json-c/json-c/issues/158) -[json_tokener.c compile error](https://api.github.com/repos/json-c/json-c/issues/159) -[missing header file on windows??](https://api.github.com/repos/json-c/json-c/issues/160) -[Is there a way to append to file?](https://api.github.com/repos/json-c/json-c/issues/161) -[json_util: add directory check for POSIX distros](https://api.github.com/repos/json-c/json-c/issues/162) -[Fix Win32 build problems](https://api.github.com/repos/json-c/json-c/issues/163) -[made it compile and link on Widnows (as static library)](https://api.github.com/repos/json-c/json-c/issues/164) -[json_object_to_json_string_ext length](https://api.github.com/repos/json-c/json-c/issues/165) -[Can't build on Windows with Visual Studio 2010](https://api.github.com/repos/json-c/json-c/issues/167) -[Tightening the number parsing algorithm](https://api.github.com/repos/json-c/json-c/issues/168) -[Doesn't compile on ubuntu 14.04, 64bit](https://api.github.com/repos/json-c/json-c/issues/169) -[Generated files in repository](https://api.github.com/repos/json-c/json-c/issues/170) -[Update configuration for VS2010 and win64](https://api.github.com/repos/json-c/json-c/issues/171) -[Adding support for parsing octal numbers](https://api.github.com/repos/json-c/json-c/issues/172) -[json_parse_int64 doesn't work correctly at illumos](https://api.github.com/repos/json-c/json-c/issues/173) -[Adding JSON_C_TO_STRING_PRETTY_TAB flag](https://api.github.com/repos/json-c/json-c/issues/174) -[make check fails 4 tests with overflows when built with ASAN](https://api.github.com/repos/json-c/json-c/issues/175) -[Possible to delete an array element at a given idx ?](https://api.github.com/repos/json-c/json-c/issues/176) -[Fix compiler warnings](https://api.github.com/repos/json-c/json-c/issues/177) -[Unable to compile on CentOS5](https://api.github.com/repos/json-c/json-c/issues/178) -[Added array_list_del_idx and json_object_array_del_idx](https://api.github.com/repos/json-c/json-c/issues/179) -[Enable silent build by default](https://api.github.com/repos/json-c/json-c/issues/180) -[json_tokener_parse_ex accepts invalid JSON](https://api.github.com/repos/json-c/json-c/issues/181) -[Link against libm when needed](https://api.github.com/repos/json-c/json-c/issues/182) -[Apply compile warning fix to master branch](https://api.github.com/repos/json-c/json-c/issues/183) -[Use only GCC-specific flags when compiling with GCC](https://api.github.com/repos/json-c/json-c/issues/184) -[compile error](https://api.github.com/repos/json-c/json-c/issues/185) -[Syntax error](https://api.github.com/repos/json-c/json-c/issues/186) -[array_list_get_idx and negative indexes.](https://api.github.com/repos/json-c/json-c/issues/187) -[json_object_object_foreach warnings](https://api.github.com/repos/json-c/json-c/issues/188) -[noisy json_object_from_file: error opening file](https://api.github.com/repos/json-c/json-c/issues/189) -[warning: initialization discards const qualifier from pointer target type \[enabled by default\]](https://api.github.com/repos/json-c/json-c/issues/190) -[json_tokener_parse accepts invalid JSON {"key": "value" , }](https://api.github.com/repos/json-c/json-c/issues/192) -[Make serialization format of doubles configurable](https://api.github.com/repos/json-c/json-c/issues/193) -[Add utility function for comparing json_objects](https://api.github.com/repos/json-c/json-c/issues/194) -[Call uselocale instead of setlocale](https://api.github.com/repos/json-c/json-c/issues/195) -[Performance improvements](https://api.github.com/repos/json-c/json-c/issues/196) -[Time for a new release?](https://api.github.com/repos/json-c/json-c/issues/197) -[Fix possible memory leak and remove superfluous NULL checks before free()](https://api.github.com/repos/json-c/json-c/issues/198) -[Fix build in Visual Studio](https://api.github.com/repos/json-c/json-c/issues/199) -[Add build scripts for CI platforms](https://api.github.com/repos/json-c/json-c/issues/200) -[disable forward-slash escaping?](https://api.github.com/repos/json-c/json-c/issues/201) -[Array with objects support](https://api.github.com/repos/json-c/json-c/issues/202) -[Add source position/coordinates to API](https://api.github.com/repos/json-c/json-c/issues/203) -[json-c/json.h not found ](https://api.github.com/repos/json-c/json-c/issues/204) -[json-c Compiled with Visual Studios](https://api.github.com/repos/json-c/json-c/issues/205) -[what do i use in place of json_object_object_get?](https://api.github.com/repos/json-c/json-c/issues/206) -[Add support for property pairs directly added to arrays](https://api.github.com/repos/json-c/json-c/issues/207) -[Performance enhancements (mainly) to json_object_to_json_string()](https://api.github.com/repos/json-c/json-c/issues/208) -[fix regression from 2d549662be832da838aa063da2efa78ee3b99668](https://api.github.com/repos/json-c/json-c/issues/209) -[Use size_t for arrays](https://api.github.com/repos/json-c/json-c/issues/210) -[Atomic updates for the refcount](https://api.github.com/repos/json-c/json-c/issues/211) -[Refcount doesn't work between threads](https://api.github.com/repos/json-c/json-c/issues/212) -[fix to compile with microsoft visual c++ 2010](https://api.github.com/repos/json-c/json-c/issues/213) -[Some non-GNU systems support __sync_val_compare_and_swap](https://api.github.com/repos/json-c/json-c/issues/214) -[Build json-c for window 64 bit.](https://api.github.com/repos/json-c/json-c/issues/215) -[configure: check realloc with AC_CHECK_FUNCS() to fix cross-compilation.](https://api.github.com/repos/json-c/json-c/issues/216) -[Checking for functions in float.h](https://api.github.com/repos/json-c/json-c/issues/217) -[Use a macro to indicate C99 to the compiler](https://api.github.com/repos/json-c/json-c/issues/218) -[Fix various potential null ptr deref and int32 overflows](https://api.github.com/repos/json-c/json-c/issues/219) -[Add utility function for comparing json_objects](https://api.github.com/repos/json-c/json-c/issues/220) -[JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly](https://api.github.com/repos/json-c/json-c/issues/221) -[Fix issue #221: JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly](https://api.github.com/repos/json-c/json-c/issues/222) -[Clarify json_object_get_string documentation of NULL handling & return](https://api.github.com/repos/json-c/json-c/issues/223) -[json_tokener.c - all warnings being treated as errors](https://api.github.com/repos/json-c/json-c/issues/224) -[Hi, will you support clib as a "registry"?](https://api.github.com/repos/json-c/json-c/issues/225) -[Bump SOVERSION to 3](https://api.github.com/repos/json-c/json-c/issues/227) -[avoid double slashes from json](https://api.github.com/repos/json-c/json-c/issues/228) -[configure fails: checking size of size_t... configure: error: cannot determine a size for size_t](https://api.github.com/repos/json-c/json-c/issues/229) -[Use stdint.h to check for size_t size](https://api.github.com/repos/json-c/json-c/issues/230) -[Fix size_t size check for first-time builds](https://api.github.com/repos/json-c/json-c/issues/231) -[tests/tests1: fix printf format for size_t arguments](https://api.github.com/repos/json-c/json-c/issues/232) -[Include stddef.h in json_object.h](https://api.github.com/repos/json-c/json-c/issues/233) -[Add public API to use userdata independently of custom serializer](https://api.github.com/repos/json-c/json-c/issues/234) -[Undefined symbols Error for architecture x86_64 on Mac ](https://api.github.com/repos/json-c/json-c/issues/235) -[Building a project which uses json-c with flag -Wcast-qual causes compilation errors](https://api.github.com/repos/json-c/json-c/issues/236) -[handle escaped utf-8](https://api.github.com/repos/json-c/json-c/issues/237) -[linkhash.c: optimised the table_free path](https://api.github.com/repos/json-c/json-c/issues/238) -[initialize null terminator of new printbuf](https://api.github.com/repos/json-c/json-c/issues/239) -[Compile error: Variable set but not used](https://api.github.com/repos/json-c/json-c/issues/240) -[getting error in date string 19\/07\/2016, fixed for error 19/07/2016](https://api.github.com/repos/json-c/json-c/issues/241) -[json_tokener_parse error](https://api.github.com/repos/json-c/json-c/issues/242) -[Fix #165](https://api.github.com/repos/json-c/json-c/issues/243) -[Error while compiling source from RHEL5, could you please help me to fix this ](https://api.github.com/repos/json-c/json-c/issues/244) -[json-c compile in window xp](https://api.github.com/repos/json-c/json-c/issues/245) -[Mac: uselocale failed to build](https://api.github.com/repos/json-c/json-c/issues/246) -[json_object_array_del_idx function has segment fault error?](https://api.github.com/repos/json-c/json-c/issues/247) -[Minor changes in C source code](https://api.github.com/repos/json-c/json-c/issues/248) -[Improving README](https://api.github.com/repos/json-c/json-c/issues/249) -[Improving .gitignore](https://api.github.com/repos/json-c/json-c/issues/250) -[Adding a file for EditorConfig](https://api.github.com/repos/json-c/json-c/issues/251) -[Very minor changes not related to C source code](https://api.github.com/repos/json-c/json-c/issues/252) -[Adding a test with cppcheck for Travis CI](https://api.github.com/repos/json-c/json-c/issues/253) -[Very minor changes to some tests](https://api.github.com/repos/json-c/json-c/issues/254) -[Minor changes in C source code](https://api.github.com/repos/json-c/json-c/issues/255) -[Mailing list dead?](https://api.github.com/repos/json-c/json-c/issues/256) -[Defining a coding style](https://api.github.com/repos/json-c/json-c/issues/257) -[Enable CI services](https://api.github.com/repos/json-c/json-c/issues/258) -[Fails to parse valid json](https://api.github.com/repos/json-c/json-c/issues/259) -[Adding an object to itself](https://api.github.com/repos/json-c/json-c/issues/260) -[Lack of proper documentation](https://api.github.com/repos/json-c/json-c/issues/261) -[Add Cmakefile and fix compiler warning.](https://api.github.com/repos/json-c/json-c/issues/262) -[Compiler Warnings with VS2015](https://api.github.com/repos/json-c/json-c/issues/263) -[successed in simple test while failed in my project](https://api.github.com/repos/json-c/json-c/issues/264) -[Conformance report for reference](https://api.github.com/repos/json-c/json-c/issues/265) -[crash perhaps related to reference counting](https://api.github.com/repos/json-c/json-c/issues/266) -[Removes me as Win32 maintainer, because I'm not.](https://api.github.com/repos/json-c/json-c/issues/267) -[Documentation of json_object_to_json_string gives no information about memory management](https://api.github.com/repos/json-c/json-c/issues/268) -[json_object__set(json_object *o, value) API for value setting in json object private structure](https://api.github.com/repos/json-c/json-c/issues/269) -[new API json_object_new_double_f(doubel d,const char * fmt);](https://api.github.com/repos/json-c/json-c/issues/270) -[Cannot compile using CMake on macOS](https://api.github.com/repos/json-c/json-c/issues/271) -[fixed wrong object name in json_object_all_values_equal](https://api.github.com/repos/json-c/json-c/issues/273) -[Support for 64 bit pointers on Windows](https://api.github.com/repos/json-c/json-c/issues/274) -[Out-of-bounds read in json_tokener_parse_ex](https://api.github.com/repos/json-c/json-c/issues/275) -[ ./configure for centos release 6.7(final) failure](https://api.github.com/repos/json-c/json-c/issues/276) -[Json object set xxx](https://api.github.com/repos/json-c/json-c/issues/277) -[Serialization of double with no fractional component drops trailing zero](https://api.github.com/repos/json-c/json-c/issues/278) -[Segmentation fault in array_list_length()](https://api.github.com/repos/json-c/json-c/issues/279) -[Should json_object_array_get_idx check whether input obj is array? ](https://api.github.com/repos/json-c/json-c/issues/280) -[how to pretty print json-c? ](https://api.github.com/repos/json-c/json-c/issues/281) -[ignore temporary files](https://api.github.com/repos/json-c/json-c/issues/282) -[json_pointer: add first revision based on RFC 6901](https://api.github.com/repos/json-c/json-c/issues/283) -[Resusing json_tokener object](https://api.github.com/repos/json-c/json-c/issues/284) -[Revert "compat/strdup.h: move common compat check for strdup() to own](https://api.github.com/repos/json-c/json-c/issues/285) -[json_tokener_parse_ex() returns json_tokener_continue on zero-length string](https://api.github.com/repos/json-c/json-c/issues/286) -[json_pointer: extend setter & getter with printf() style arguments](https://api.github.com/repos/json-c/json-c/issues/287) -[Fix _GNU_SOURCE define for vasprintf](https://api.github.com/repos/json-c/json-c/issues/288) -[bugfix: floating point representaion without fractional part ](https://api.github.com/repos/json-c/json-c/issues/289) -[duplicate an json_object](https://api.github.com/repos/json-c/json-c/issues/290) -[isspace assert error](https://api.github.com/repos/json-c/json-c/issues/291) -[configure error "./configure: line 13121: syntax error near unexpected token `-Wall'"](https://api.github.com/repos/json-c/json-c/issues/292) -[how to make with bitcode for ios](https://api.github.com/repos/json-c/json-c/issues/293) -[Adding UTF-8 validation. Fixes #122](https://api.github.com/repos/json-c/json-c/issues/294) -[cross compile w/ mingw](https://api.github.com/repos/json-c/json-c/issues/295) -[Missing functions header in json_object.h](https://api.github.com/repos/json-c/json-c/issues/296) -[could not parse string to Json object? Like string str=\"helloworld;E\\test\\log\\;end\"](https://api.github.com/repos/json-c/json-c/issues/297) -[Building using CMake doesn't work](https://api.github.com/repos/json-c/json-c/issues/298) -[Improve json_object -> string performance](https://api.github.com/repos/json-c/json-c/issues/299) -[Running tests with MinGW build](https://api.github.com/repos/json-c/json-c/issues/300) -[How to deep copy json_object in C++ ?](https://api.github.com/repos/json-c/json-c/issues/301) -[json_tokener_parse_ex doesn't parse JSON values](https://api.github.com/repos/json-c/json-c/issues/302) -[fix doc in tokener header file](https://api.github.com/repos/json-c/json-c/issues/303) -[(.text+0x72846): undefined reference to `is_error'](https://api.github.com/repos/json-c/json-c/issues/304) -[Fix compilation without C-99 option](https://api.github.com/repos/json-c/json-c/issues/305) -[./configure: line 12748 -error=deprecated-declarations](https://api.github.com/repos/json-c/json-c/issues/306) -[Memory leak in json_tokener_parse](https://api.github.com/repos/json-c/json-c/issues/307) -[AM_PROG_LIBTOOL not found on Linux](https://api.github.com/repos/json-c/json-c/issues/308) -[GCC 7 reports various -Wimplicit-fallthrough= errors](https://api.github.com/repos/json-c/json-c/issues/309) -[Add FALLTHRU comment to handle GCC7 warnings.](https://api.github.com/repos/json-c/json-c/issues/310) -[Fix error C3688 when compiling on Visual Studio 2015](https://api.github.com/repos/json-c/json-c/issues/311) -[Fix CMake Build process improved for MinGW and MSYS2](https://api.github.com/repos/json-c/json-c/issues/312) -[VERBOSE=1 make check; tests/test_util_file.test.c and tests/test_util_file.expected out of sync](https://api.github.com/repos/json-c/json-c/issues/313) -[Passing -1 to json_tokener_parse_ex is possibly unsafe](https://api.github.com/repos/json-c/json-c/issues/315) -[Memory Returned by json_object_to_json_string not freed](https://api.github.com/repos/json-c/json-c/issues/316) -[json_object_get_string gives segmentation error](https://api.github.com/repos/json-c/json-c/issues/317) -[PVS-Studio static analyzer analyze results](https://api.github.com/repos/json-c/json-c/issues/318) -[Windows: Fix dynamic library build with Visual Studio](https://api.github.com/repos/json-c/json-c/issues/319) -[Can't compile in Mac OS X El Capitan](https://api.github.com/repos/json-c/json-c/issues/320) -[build,cmake: fix vasprintf implicit definition and generate both static & shared libs](https://api.github.com/repos/json-c/json-c/issues/321) -[can not link with libjson-c.a](https://api.github.com/repos/json-c/json-c/issues/322) -[implicit fallthrough detected by gcc 7.1](https://api.github.com/repos/json-c/json-c/issues/323) -[JsonPath like function?](https://api.github.com/repos/json-c/json-c/issues/324) -[Fix stack buffer overflow in json_object_double_to_json_string_format()](https://api.github.com/repos/json-c/json-c/issues/325) -[why json-c so hard to compile](https://api.github.com/repos/json-c/json-c/issues/327) -[json_object: implement json_object_deep_copy() function](https://api.github.com/repos/json-c/json-c/issues/328) -[build,cmake: build,cmake: rename libjson-c-static.a to libjson-c.a](https://api.github.com/repos/json-c/json-c/issues/329) -[tests: symlink basic tests to a single file that has the common code](https://api.github.com/repos/json-c/json-c/issues/330) -[Safe use of snprintf() / vsnprintf() for Visual studio, and thread-safety fix](https://api.github.com/repos/json-c/json-c/issues/331) -[Valgrind: invalid read after json_object_array_del_idx.](https://api.github.com/repos/json-c/json-c/issues/332) -[Replace obsolete AM_PROG_LIBTOOL](https://api.github.com/repos/json-c/json-c/issues/333) -[README.md: show build status tag from travis-ci.org](https://api.github.com/repos/json-c/json-c/issues/335) -[tests: fix tests in travis-ci.org](https://api.github.com/repos/json-c/json-c/issues/336) -[Synchronize "potentially racy" random seed in lh_char_hash()](https://api.github.com/repos/json-c/json-c/issues/337) -[implement json_object_int_inc(json_object *, int64_t)](https://api.github.com/repos/json-c/json-c/issues/338) -[Json schema validation](https://api.github.com/repos/json-c/json-c/issues/339) -[strerror_override: add extern "C" and JSON_EXPORT specifiers for Visual C++ compilers](https://api.github.com/repos/json-c/json-c/issues/340) -[character "/" parse as "\/"](https://api.github.com/repos/json-c/json-c/issues/341) -[ No such file or directory "/usr/include/json.h"](https://api.github.com/repos/json-c/json-c/issues/342) -[Can't parse json](https://api.github.com/repos/json-c/json-c/issues/343) -[Fix Mingw build](https://api.github.com/repos/json-c/json-c/issues/344) -[Fix make dist and make distcheck](https://api.github.com/repos/json-c/json-c/issues/345) -[Clamp double to int32 when narrowing in json_object_get_int.](https://api.github.com/repos/json-c/json-c/issues/346) -[MSVC linker error json_c_strerror](https://api.github.com/repos/json-c/json-c/issues/347) -[why](https://api.github.com/repos/json-c/json-c/issues/348) -[`missing` is missing?](https://api.github.com/repos/json-c/json-c/issues/349) -[stderror-override and disable-shared](https://api.github.com/repos/json-c/json-c/issues/350) -[SIZE_T_MAX redefined from limits.h](https://api.github.com/repos/json-c/json-c/issues/351) -[`INSTALL` overrides an automake script.](https://api.github.com/repos/json-c/json-c/issues/352) -[Documentation issues](https://api.github.com/repos/json-c/json-c/issues/353) -[Fixes #351 #352 #353 ](https://api.github.com/repos/json-c/json-c/issues/354) -[1.make it can been compiled with Visual Studio 2010 by modify the CMakeList.txt and others](https://api.github.com/repos/json-c/json-c/issues/355) -[VS2008 test test_util_file.cpp err!](https://api.github.com/repos/json-c/json-c/issues/356) -[__json_c_strerror incompatibility with link-time optimization](https://api.github.com/repos/json-c/json-c/issues/357) -[make issue](https://api.github.com/repos/json-c/json-c/issues/358) -[update CMakeLists.txt for compile with visual studio at least 2010](https://api.github.com/repos/json-c/json-c/issues/359) -[Use strtoll() to parse ints](https://api.github.com/repos/json-c/json-c/issues/360) -[Fix double to int cast overflow in json_object_get_int64.](https://api.github.com/repos/json-c/json-c/issues/361) -[CMake Package Config](https://api.github.com/repos/json-c/json-c/issues/362) -[Issue #338, add json_object_add_int functions](https://api.github.com/repos/json-c/json-c/issues/363) -[Cmake is Errir](https://api.github.com/repos/json-c/json-c/issues/364) -[added fallthrough for gcc7](https://api.github.com/repos/json-c/json-c/issues/365) -[how to check the json string,crash!](https://api.github.com/repos/json-c/json-c/issues/366) -[Is json-c support "redirect" semantic?](https://api.github.com/repos/json-c/json-c/issues/367) -[Add examples](https://api.github.com/repos/json-c/json-c/issues/368) -[How to build json-c library for android?](https://api.github.com/repos/json-c/json-c/issues/369) -[Compiling using clang-cl](https://api.github.com/repos/json-c/json-c/issues/370) -[Invalid parsing for Infinity with json-c 0.12](https://api.github.com/repos/json-c/json-c/issues/371) -[Json-c 0.12: Fixed Infinity bug](https://api.github.com/repos/json-c/json-c/issues/372) -[build: fix build on appveyor CI](https://api.github.com/repos/json-c/json-c/issues/373) -[Undefined symbols for architecture x86_64:](https://api.github.com/repos/json-c/json-c/issues/374) -[what would happened when json_object_object_add add the same key](https://api.github.com/repos/json-c/json-c/issues/375) -[Eclipse error ](https://api.github.com/repos/json-c/json-c/issues/376) -[on gcc 7.2.0 on my linux distribution with json-c 2013-04-02 source](https://api.github.com/repos/json-c/json-c/issues/377) -[ Eclipse: library (libjson-c) not found, but configured](https://api.github.com/repos/json-c/json-c/issues/378) -[error: this statement may fall through \[-Werror=implicit-fallthrough=\]](https://api.github.com/repos/json-c/json-c/issues/379) -[Build on Windows](https://api.github.com/repos/json-c/json-c/issues/380) -[Fix makedist](https://api.github.com/repos/json-c/json-c/issues/381) -[Memory leak for json_tokener_parse_ex for version 0.12.1](https://api.github.com/repos/json-c/json-c/issues/382) -[Fix a compiler warning.](https://api.github.com/repos/json-c/json-c/issues/383) -[Fix a VS 2015 compiler warnings.](https://api.github.com/repos/json-c/json-c/issues/384) +* [Issue #61](https://github.com/json-c/json-c/issues/61) - Make json_object_object_add() indicate success or failure, test fix \ +* [Issue #113](https://github.com/json-c/json-c/issues/113) - Build fixes (make dist and make distcheck) \ +* [Issue #124](https://github.com/json-c/json-c/issues/124) - Fixing build \ +* [Issue #125](https://github.com/json-c/json-c/issues/125) - Fix compile error(variable size set but not used) on g++4.6 \ +* [Issue #126](https://github.com/json-c/json-c/issues/126) - Removed unused size variable. \ +* [Issue #127](https://github.com/json-c/json-c/issues/127) - remove unused `size` variable \ +* [Issue #128](https://github.com/json-c/json-c/issues/128) - Remove unused variable from json_tokenizer.c \ +* [Issue #130](https://github.com/json-c/json-c/issues/130) - Failed to compile under Ubuntu 13.10 32bit \ +* [Issue #131](https://github.com/json-c/json-c/issues/131) - undefined symbol: __sync_val_compare_and_swap_4 \ +* [Issue #132](https://github.com/json-c/json-c/issues/132) - Remove unused variable 'size' \ +* [Issue #133](https://github.com/json-c/json-c/issues/133) - Update and rename README to README.md \ +* [Issue #134](https://github.com/json-c/json-c/issues/134) - Must remove variable size... \ +* [Issue #135](https://github.com/json-c/json-c/issues/135) - bits.h uses removed json_tokener_errors\[error\] \ +* [Issue #136](https://github.com/json-c/json-c/issues/136) - Error when running make check \ +* [Issue #137](https://github.com/json-c/json-c/issues/137) - config.h.in should not be in git \ +* [Issue #138](https://github.com/json-c/json-c/issues/138) - Can't build on RHEL 6.5 due to dependency on automake-1.14 \ +* [Issue #140](https://github.com/json-c/json-c/issues/140) - Code bug in random_test.c evaluating same expression twice \ +* [Issue #141](https://github.com/json-c/json-c/issues/141) - Removed duplicate check in random_seed test - bug #140 \ +* [Issue #142](https://github.com/json-c/json-c/issues/142) - Please undeprecate json_object_object_get \ +* [Issue #144](https://github.com/json-c/json-c/issues/144) - Introduce json_object_from_fd \ +* [Issue #145](https://github.com/json-c/json-c/issues/145) - Handle % character properly \ +* [Issue #146](https://github.com/json-c/json-c/issues/146) - TAGS rename \ +* [Issue #148](https://github.com/json-c/json-c/issues/148) - Bump the soname \ +* [Issue #149](https://github.com/json-c/json-c/issues/149) - SONAME bump \ +* [Issue #150](https://github.com/json-c/json-c/issues/150) - Fix build using MinGW. \ +* [Issue #151](https://github.com/json-c/json-c/issues/151) - Remove json_type enum trailing comma \ +* [Issue #152](https://github.com/json-c/json-c/issues/152) - error while compiling json-c library version 0.11 \ +* [Issue #153](https://github.com/json-c/json-c/issues/153) - improve doc for json_object_to_json_string() \ +* [Issue #154](https://github.com/json-c/json-c/issues/154) - double precision \ +* [Issue #155](https://github.com/json-c/json-c/issues/155) - add bsearch for arrays \ +* [Issue #156](https://github.com/json-c/json-c/issues/156) - Remove trailing whitespaces \ +* [Issue #157](https://github.com/json-c/json-c/issues/157) - JSON-C shall not exit on calloc fail. \ +* [Issue #158](https://github.com/json-c/json-c/issues/158) - while using json-c 0.11, I am facing strange crash issue in json_object_put. \ +* [Issue #159](https://github.com/json-c/json-c/issues/159) - json_tokener.c compile error \ +* [Issue #160](https://github.com/json-c/json-c/issues/160) - missing header file on windows?? \ +* [Issue #161](https://github.com/json-c/json-c/issues/161) - Is there a way to append to file? \ +* [Issue #162](https://github.com/json-c/json-c/issues/162) - json_util: add directory check for POSIX distros \ +* [Issue #163](https://github.com/json-c/json-c/issues/163) - Fix Win32 build problems \ +* [Issue #164](https://github.com/json-c/json-c/issues/164) - made it compile and link on Widnows (as static library) \ +* [Issue #165](https://github.com/json-c/json-c/issues/165) - json_object_to_json_string_ext length \ +* [Issue #167](https://github.com/json-c/json-c/issues/167) - Can't build on Windows with Visual Studio 2010 \ +* [Issue #168](https://github.com/json-c/json-c/issues/168) - Tightening the number parsing algorithm \ +* [Issue #169](https://github.com/json-c/json-c/issues/169) - Doesn't compile on ubuntu 14.04, 64bit \ +* [Issue #170](https://github.com/json-c/json-c/issues/170) - Generated files in repository \ +* [Issue #171](https://github.com/json-c/json-c/issues/171) - Update configuration for VS2010 and win64 \ +* [Issue #172](https://github.com/json-c/json-c/issues/172) - Adding support for parsing octal numbers \ +* [Issue #173](https://github.com/json-c/json-c/issues/173) - json_parse_int64 doesn't work correctly at illumos \ +* [Issue #174](https://github.com/json-c/json-c/issues/174) - Adding JSON_C_TO_STRING_PRETTY_TAB flag \ +* [Issue #175](https://github.com/json-c/json-c/issues/175) - make check fails 4 tests with overflows when built with ASAN \ +* [Issue #176](https://github.com/json-c/json-c/issues/176) - Possible to delete an array element at a given idx ? \ +* [Issue #177](https://github.com/json-c/json-c/issues/177) - Fix compiler warnings \ +* [Issue #178](https://github.com/json-c/json-c/issues/178) - Unable to compile on CentOS5 \ +* [Issue #179](https://github.com/json-c/json-c/issues/179) - Added array_list_del_idx and json_object_array_del_idx \ +* [Issue #180](https://github.com/json-c/json-c/issues/180) - Enable silent build by default \ +* [Issue #181](https://github.com/json-c/json-c/issues/181) - json_tokener_parse_ex accepts invalid JSON \ +* [Issue #182](https://github.com/json-c/json-c/issues/182) - Link against libm when needed \ +* [Issue #183](https://github.com/json-c/json-c/issues/183) - Apply compile warning fix to master branch \ +* [Issue #184](https://github.com/json-c/json-c/issues/184) - Use only GCC-specific flags when compiling with GCC \ +* [Issue #185](https://github.com/json-c/json-c/issues/185) - compile error \ +* [Issue #186](https://github.com/json-c/json-c/issues/186) - Syntax error \ +* [Issue #187](https://github.com/json-c/json-c/issues/187) - array_list_get_idx and negative indexes. \ +* [Issue #188](https://github.com/json-c/json-c/issues/188) - json_object_object_foreach warnings \ +* [Issue #189](https://github.com/json-c/json-c/issues/189) - noisy json_object_from_file: error opening file \ +* [Issue #190](https://github.com/json-c/json-c/issues/190) - warning: initialization discards const qualifier from pointer target type \[enabled by default\] \ +* [Issue #192](https://github.com/json-c/json-c/issues/192) - json_tokener_parse accepts invalid JSON {"key": "value" , } \ +* [Issue #193](https://github.com/json-c/json-c/issues/193) - Make serialization format of doubles configurable \ +* [Issue #194](https://github.com/json-c/json-c/issues/194) - Add utility function for comparing json_objects \ +* [Issue #195](https://github.com/json-c/json-c/issues/195) - Call uselocale instead of setlocale \ +* [Issue #196](https://github.com/json-c/json-c/issues/196) - Performance improvements \ +* [Issue #197](https://github.com/json-c/json-c/issues/197) - Time for a new release? \ +* [Issue #198](https://github.com/json-c/json-c/issues/198) - Fix possible memory leak and remove superfluous NULL checks before free() \ +* [Issue #199](https://github.com/json-c/json-c/issues/199) - Fix build in Visual Studio \ +* [Issue #200](https://github.com/json-c/json-c/issues/200) - Add build scripts for CI platforms \ +* [Issue #201](https://github.com/json-c/json-c/issues/201) - disable forward-slash escaping? \ +* [Issue #202](https://github.com/json-c/json-c/issues/202) - Array with objects support \ +* [Issue #203](https://github.com/json-c/json-c/issues/203) - Add source position/coordinates to API \ +* [Issue #204](https://github.com/json-c/json-c/issues/204) - json-c/json.h not found \ +* [Issue #205](https://github.com/json-c/json-c/issues/205) - json-c Compiled with Visual Studios \ +* [Issue #206](https://github.com/json-c/json-c/issues/206) - what do i use in place of json_object_object_get? \ +* [Issue #207](https://github.com/json-c/json-c/issues/207) - Add support for property pairs directly added to arrays \ +* [Issue #208](https://github.com/json-c/json-c/issues/208) - Performance enhancements (mainly) to json_object_to_json_string() \ +* [Issue #209](https://github.com/json-c/json-c/issues/209) - fix regression from 2d549662be832da838aa063da2efa78ee3b99668 \ +* [Issue #210](https://github.com/json-c/json-c/issues/210) - Use size_t for arrays \ +* [Issue #211](https://github.com/json-c/json-c/issues/211) - Atomic updates for the refcount \ +* [Issue #212](https://github.com/json-c/json-c/issues/212) - Refcount doesn't work between threads \ +* [Issue #213](https://github.com/json-c/json-c/issues/213) - fix to compile with microsoft visual c++ 2010 \ +* [Issue #214](https://github.com/json-c/json-c/issues/214) - Some non-GNU systems support __sync_val_compare_and_swap \ +* [Issue #215](https://github.com/json-c/json-c/issues/215) - Build json-c for window 64 bit. \ +* [Issue #216](https://github.com/json-c/json-c/issues/216) - configure: check realloc with AC_CHECK_FUNCS() to fix cross-compilation. \ +* [Issue #217](https://github.com/json-c/json-c/issues/217) - Checking for functions in float.h \ +* [Issue #218](https://github.com/json-c/json-c/issues/218) - Use a macro to indicate C99 to the compiler \ +* [Issue #219](https://github.com/json-c/json-c/issues/219) - Fix various potential null ptr deref and int32 overflows \ +* [Issue #220](https://github.com/json-c/json-c/issues/220) - Add utility function for comparing json_objects \ +* [Issue #221](https://github.com/json-c/json-c/issues/221) - JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly \ +* [Issue #222](https://github.com/json-c/json-c/issues/222) - Fix issue #221: JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly \ +* [Issue #223](https://github.com/json-c/json-c/issues/223) - Clarify json_object_get_string documentation of NULL handling & return \ +* [Issue #224](https://github.com/json-c/json-c/issues/224) - json_tokener.c - all warnings being treated as errors \ +* [Issue #225](https://github.com/json-c/json-c/issues/225) - Hi, will you support clib as a "registry"? \ +* [Issue #227](https://github.com/json-c/json-c/issues/227) - Bump SOVERSION to 3 \ +* [Issue #228](https://github.com/json-c/json-c/issues/228) - avoid double slashes from json \ +* [Issue #229](https://github.com/json-c/json-c/issues/229) - configure fails: checking size of size_t... configure: error: cannot determine a size for size_t \ +* [Issue #230](https://github.com/json-c/json-c/issues/230) - Use stdint.h to check for size_t size \ +* [Issue #231](https://github.com/json-c/json-c/issues/231) - Fix size_t size check for first-time builds \ +* [Issue #232](https://github.com/json-c/json-c/issues/232) - tests/tests1: fix printf format for size_t arguments \ +* [Issue #233](https://github.com/json-c/json-c/issues/233) - Include stddef.h in json_object.h \ +* [Issue #234](https://github.com/json-c/json-c/issues/234) - Add public API to use userdata independently of custom serializer \ +* [Issue #235](https://github.com/json-c/json-c/issues/235) - Undefined symbols Error for architecture x86_64 on Mac \ +* [Issue #236](https://github.com/json-c/json-c/issues/236) - Building a project which uses json-c with flag -Wcast-qual causes compilation errors \ +* [Issue #237](https://github.com/json-c/json-c/issues/237) - handle escaped utf-8 \ +* [Issue #238](https://github.com/json-c/json-c/issues/238) - linkhash.c: optimised the table_free path \ +* [Issue #239](https://github.com/json-c/json-c/issues/239) - initialize null terminator of new printbuf \ +* [Issue #240](https://github.com/json-c/json-c/issues/240) - Compile error: Variable set but not used \ +* [Issue #241](https://github.com/json-c/json-c/issues/241) - getting error in date string 19\/07\/2016, fixed for error 19/07/2016 \ +* [Issue #242](https://github.com/json-c/json-c/issues/242) - json_tokener_parse error \ +* [Issue #243](https://github.com/json-c/json-c/issues/243) - Fix #165 \ +* [Issue #244](https://github.com/json-c/json-c/issues/244) - Error while compiling source from RHEL5, could you please help me to fix this \ +* [Issue #245](https://github.com/json-c/json-c/issues/245) - json-c compile in window xp \ +* [Issue #246](https://github.com/json-c/json-c/issues/246) - Mac: uselocale failed to build \ +* [Issue #247](https://github.com/json-c/json-c/issues/247) - json_object_array_del_idx function has segment fault error? \ +* [Issue #248](https://github.com/json-c/json-c/issues/248) - Minor changes in C source code \ +* [Issue #249](https://github.com/json-c/json-c/issues/249) - Improving README \ +* [Issue #250](https://github.com/json-c/json-c/issues/250) - Improving .gitignore \ +* [Issue #251](https://github.com/json-c/json-c/issues/251) - Adding a file for EditorConfig \ +* [Issue #252](https://github.com/json-c/json-c/issues/252) - Very minor changes not related to C source code \ +* [Issue #253](https://github.com/json-c/json-c/issues/253) - Adding a test with cppcheck for Travis CI \ +* [Issue #254](https://github.com/json-c/json-c/issues/254) - Very minor changes to some tests \ +* [Issue #255](https://github.com/json-c/json-c/issues/255) - Minor changes in C source code \ +* [Issue #256](https://github.com/json-c/json-c/issues/256) - Mailing list dead? \ +* [Issue #257](https://github.com/json-c/json-c/issues/257) - Defining a coding style \ +* [Issue #258](https://github.com/json-c/json-c/issues/258) - Enable CI services \ +* [Issue #259](https://github.com/json-c/json-c/issues/259) - Fails to parse valid json \ +* [Issue #260](https://github.com/json-c/json-c/issues/260) - Adding an object to itself \ +* [Issue #261](https://github.com/json-c/json-c/issues/261) - Lack of proper documentation \ +* [Issue #262](https://github.com/json-c/json-c/issues/262) - Add Cmakefile and fix compiler warning. \ +* [Issue #263](https://github.com/json-c/json-c/issues/263) - Compiler Warnings with VS2015 \ +* [Issue #264](https://github.com/json-c/json-c/issues/264) - successed in simple test while failed in my project \ +* [Issue #265](https://github.com/json-c/json-c/issues/265) - Conformance report for reference \ +* [Issue #266](https://github.com/json-c/json-c/issues/266) - crash perhaps related to reference counting \ +* [Issue #267](https://github.com/json-c/json-c/issues/267) - Removes me as Win32 maintainer, because I'm not. \ +* [Issue #268](https://github.com/json-c/json-c/issues/268) - Documentation of json_object_to_json_string gives no information about memory management \ +* [Issue #269](https://github.com/json-c/json-c/issues/269) - json_object__set(json_object *o, value) API for value setting in json object private structure \ +* [Issue #270](https://github.com/json-c/json-c/issues/270) - new API json_object_new_double_f(doubel d,const char * fmt); \ +* [Issue #271](https://github.com/json-c/json-c/issues/271) - Cannot compile using CMake on macOS \ +* [Issue #273](https://github.com/json-c/json-c/issues/273) - fixed wrong object name in json_object_all_values_equal \ +* [Issue #274](https://github.com/json-c/json-c/issues/274) - Support for 64 bit pointers on Windows \ +* [Issue #275](https://github.com/json-c/json-c/issues/275) - Out-of-bounds read in json_tokener_parse_ex \ +* [Issue #276](https://github.com/json-c/json-c/issues/276) - ./configure for centos release 6.7(final) failure \ +* [Issue #277](https://github.com/json-c/json-c/issues/277) - Json object set xxx \ +* [Issue #278](https://github.com/json-c/json-c/issues/278) - Serialization of double with no fractional component drops trailing zero \ +* [Issue #279](https://github.com/json-c/json-c/issues/279) - Segmentation fault in array_list_length() \ +* [Issue #280](https://github.com/json-c/json-c/issues/280) - Should json_object_array_get_idx check whether input obj is array? \ +* [Issue #281](https://github.com/json-c/json-c/issues/281) - how to pretty print json-c? \ +* [Issue #282](https://github.com/json-c/json-c/issues/282) - ignore temporary files \ +* [Issue #283](https://github.com/json-c/json-c/issues/283) - json_pointer: add first revision based on RFC 6901 \ +* [Issue #284](https://github.com/json-c/json-c/issues/284) - Resusing json_tokener object \ +* [Issue #285](https://github.com/json-c/json-c/issues/285) - Revert "compat/strdup.h: move common compat check for strdup() to own \ +* [Issue #286](https://github.com/json-c/json-c/issues/286) - json_tokener_parse_ex() returns json_tokener_continue on zero-length string \ +* [Issue #287](https://github.com/json-c/json-c/issues/287) - json_pointer: extend setter & getter with printf() style arguments \ +* [Issue #288](https://github.com/json-c/json-c/issues/288) - Fix _GNU_SOURCE define for vasprintf \ +* [Issue #289](https://github.com/json-c/json-c/issues/289) - bugfix: floating point representaion without fractional part \ +* [Issue #290](https://github.com/json-c/json-c/issues/290) - duplicate an json_object \ +* [Issue #291](https://github.com/json-c/json-c/issues/291) - isspace assert error \ +* [Issue #292](https://github.com/json-c/json-c/issues/292) - configure error "./configure: line 13121: syntax error near unexpected token `-Wall'" \ +* [Issue #293](https://github.com/json-c/json-c/issues/293) - how to make with bitcode for ios \ +* [Issue #294](https://github.com/json-c/json-c/issues/294) - Adding UTF-8 validation. Fixes #122 \ +* [Issue #295](https://github.com/json-c/json-c/issues/295) - cross compile w/ mingw \ +* [Issue #296](https://github.com/json-c/json-c/issues/296) - Missing functions header in json_object.h \ +* [Issue #297](https://github.com/json-c/json-c/issues/297) - could not parse string to Json object? Like string str=\"helloworld;E\\test\\log\\;end\" \ +* [Issue #298](https://github.com/json-c/json-c/issues/298) - Building using CMake doesn't work \ +* [Issue #299](https://github.com/json-c/json-c/issues/299) - Improve json_object -> string performance \ +* [Issue #300](https://github.com/json-c/json-c/issues/300) - Running tests with MinGW build \ +* [Issue #301](https://github.com/json-c/json-c/issues/301) - How to deep copy json_object in C++ ? \ +* [Issue #302](https://github.com/json-c/json-c/issues/302) - json_tokener_parse_ex doesn't parse JSON values \ +* [Issue #303](https://github.com/json-c/json-c/issues/303) - fix doc in tokener header file \ +* [Issue #304](https://github.com/json-c/json-c/issues/304) - (.text+0x72846): undefined reference to `is_error' \ +* [Issue #305](https://github.com/json-c/json-c/issues/305) - Fix compilation without C-99 option \ +* [Issue #306](https://github.com/json-c/json-c/issues/306) - ./configure: line 12748 -error=deprecated-declarations \ +* [Issue #307](https://github.com/json-c/json-c/issues/307) - Memory leak in json_tokener_parse \ +* [Issue #308](https://github.com/json-c/json-c/issues/308) - AM_PROG_LIBTOOL not found on Linux \ +* [Issue #309](https://github.com/json-c/json-c/issues/309) - GCC 7 reports various -Wimplicit-fallthrough= errors \ +* [Issue #310](https://github.com/json-c/json-c/issues/310) - Add FALLTHRU comment to handle GCC7 warnings. \ +* [Issue #311](https://github.com/json-c/json-c/issues/311) - Fix error C3688 when compiling on Visual Studio 2015 \ +* [Issue #312](https://github.com/json-c/json-c/issues/312) - Fix CMake Build process improved for MinGW and MSYS2 \ +* [Issue #313](https://github.com/json-c/json-c/issues/313) - VERBOSE=1 make check; tests/test_util_file.test.c and tests/test_util_file.expected out of sync \ +* [Issue #315](https://github.com/json-c/json-c/issues/315) - Passing -1 to json_tokener_parse_ex is possibly unsafe \ +* [Issue #316](https://github.com/json-c/json-c/issues/316) - Memory Returned by json_object_to_json_string not freed \ +* [Issue #317](https://github.com/json-c/json-c/issues/317) - json_object_get_string gives segmentation error \ +* [Issue #318](https://github.com/json-c/json-c/issues/318) - PVS-Studio static analyzer analyze results \ +* [Issue #319](https://github.com/json-c/json-c/issues/319) - Windows: Fix dynamic library build with Visual Studio \ +* [Issue #320](https://github.com/json-c/json-c/issues/320) - Can't compile in Mac OS X El Capitan \ +* [Issue #321](https://github.com/json-c/json-c/issues/321) - build,cmake: fix vasprintf implicit definition and generate both static & shared libs \ +* [Issue #322](https://github.com/json-c/json-c/issues/322) - can not link with libjson-c.a \ +* [Issue #323](https://github.com/json-c/json-c/issues/323) - implicit fallthrough detected by gcc 7.1 \ +* [Issue #324](https://github.com/json-c/json-c/issues/324) - JsonPath like function? \ +* [Issue #325](https://github.com/json-c/json-c/issues/325) - Fix stack buffer overflow in json_object_double_to_json_string_format() \ +* [Issue #327](https://github.com/json-c/json-c/issues/327) - why json-c so hard to compile \ +* [Issue #328](https://github.com/json-c/json-c/issues/328) - json_object: implement json_object_deep_copy() function \ +* [Issue #329](https://github.com/json-c/json-c/issues/329) - build,cmake: build,cmake: rename libjson-c-static.a to libjson-c.a \ +* [Issue #330](https://github.com/json-c/json-c/issues/330) - tests: symlink basic tests to a single file that has the common code \ +* [Issue #331](https://github.com/json-c/json-c/issues/331) - Safe use of snprintf() / vsnprintf() for Visual studio, and thread-safety fix \ +* [Issue #332](https://github.com/json-c/json-c/issues/332) - Valgrind: invalid read after json_object_array_del_idx. \ +* [Issue #333](https://github.com/json-c/json-c/issues/333) - Replace obsolete AM_PROG_LIBTOOL \ +* [Issue #335](https://github.com/json-c/json-c/issues/335) - README.md: show build status tag from travis-ci.org \ +* [Issue #336](https://github.com/json-c/json-c/issues/336) - tests: fix tests in travis-ci.org \ +* [Issue #337](https://github.com/json-c/json-c/issues/337) - Synchronize "potentially racy" random seed in lh_char_hash() \ +* [Issue #338](https://github.com/json-c/json-c/issues/338) - implement json_object_int_inc(json_object *, int64_t) \ +* [Issue #339](https://github.com/json-c/json-c/issues/339) - Json schema validation \ +* [Issue #340](https://github.com/json-c/json-c/issues/340) - strerror_override: add extern "C" and JSON_EXPORT specifiers for Visual C++ compilers \ +* [Issue #341](https://github.com/json-c/json-c/issues/341) - character "/" parse as "\/" \ +* [Issue #342](https://github.com/json-c/json-c/issues/342) - No such file or directory "/usr/include/json.h" \ +* [Issue #343](https://github.com/json-c/json-c/issues/343) - Can't parse json \ +* [Issue #344](https://github.com/json-c/json-c/issues/344) - Fix Mingw build \ +* [Issue #345](https://github.com/json-c/json-c/issues/345) - Fix make dist and make distcheck \ +* [Issue #346](https://github.com/json-c/json-c/issues/346) - Clamp double to int32 when narrowing in json_object_get_int. \ +* [Issue #347](https://github.com/json-c/json-c/issues/347) - MSVC linker error json_c_strerror \ +* [Issue #348](https://github.com/json-c/json-c/issues/348) - why \ +* [Issue #349](https://github.com/json-c/json-c/issues/349) - `missing` is missing? \ +* [Issue #350](https://github.com/json-c/json-c/issues/350) - stderror-override and disable-shared \ +* [Issue #351](https://github.com/json-c/json-c/issues/351) - SIZE_T_MAX redefined from limits.h \ +* [Issue #352](https://github.com/json-c/json-c/issues/352) - `INSTALL` overrides an automake script. \ +* [Issue #353](https://github.com/json-c/json-c/issues/353) - Documentation issues \ +* [Issue #354](https://github.com/json-c/json-c/issues/354) - Fixes #351 #352 #353 \ +* [Issue #355](https://github.com/json-c/json-c/issues/355) - 1.make it can been compiled with Visual Studio 2010 by modify the CMakeList.txt and others \ +* [Issue #356](https://github.com/json-c/json-c/issues/356) - VS2008 test test_util_file.cpp err! \ +* [Issue #357](https://github.com/json-c/json-c/issues/357) - __json_c_strerror incompatibility with link-time optimization \ +* [Issue #358](https://github.com/json-c/json-c/issues/358) - make issue \ +* [Issue #359](https://github.com/json-c/json-c/issues/359) - update CMakeLists.txt for compile with visual studio at least 2010 \ +* [Issue #360](https://github.com/json-c/json-c/issues/360) - Use strtoll() to parse ints \ +* [Issue #361](https://github.com/json-c/json-c/issues/361) - Fix double to int cast overflow in json_object_get_int64. \ +* [Issue #362](https://github.com/json-c/json-c/issues/362) - CMake Package Config \ +* [Issue #363](https://github.com/json-c/json-c/issues/363) - Issue #338, add json_object_add_int functions \ +* [Issue #364](https://github.com/json-c/json-c/issues/364) - Cmake is Errir \ +* [Issue #365](https://github.com/json-c/json-c/issues/365) - added fallthrough for gcc7 \ +* [Issue #366](https://github.com/json-c/json-c/issues/366) - how to check the json string,crash! \ +* [Issue #367](https://github.com/json-c/json-c/issues/367) - Is json-c support "redirect" semantic? \ +* [Issue #368](https://github.com/json-c/json-c/issues/368) - Add examples \ +* [Issue #369](https://github.com/json-c/json-c/issues/369) - How to build json-c library for android? \ +* [Issue #370](https://github.com/json-c/json-c/issues/370) - Compiling using clang-cl \ +* [Issue #371](https://github.com/json-c/json-c/issues/371) - Invalid parsing for Infinity with json-c 0.12 \ +* [Issue #372](https://github.com/json-c/json-c/issues/372) - Json-c 0.12: Fixed Infinity bug \ +* [Issue #373](https://github.com/json-c/json-c/issues/373) - build: fix build on appveyor CI \ +* [Issue #374](https://github.com/json-c/json-c/issues/374) - Undefined symbols for architecture x86_64: \ +* [Issue #375](https://github.com/json-c/json-c/issues/375) - what would happened when json_object_object_add add the same key \ +* [Issue #376](https://github.com/json-c/json-c/issues/376) - Eclipse error \ +* [Issue #377](https://github.com/json-c/json-c/issues/377) - on gcc 7.2.0 on my linux distribution with json-c 2013-04-02 source \ +* [Issue #378](https://github.com/json-c/json-c/issues/378) - Eclipse: library (libjson-c) not found, but configured \ +* [Issue #379](https://github.com/json-c/json-c/issues/379) - error: this statement may fall through \[-Werror=implicit-fallthrough=\] \ +* [Issue #380](https://github.com/json-c/json-c/issues/380) - Build on Windows \ +* [Issue #381](https://github.com/json-c/json-c/issues/381) - Fix makedist \ +* [Issue #382](https://github.com/json-c/json-c/issues/382) - Memory leak for json_tokener_parse_ex for version 0.12.1 \ +* [Issue #383](https://github.com/json-c/json-c/issues/383) - Fix a compiler warning. \ +* [Issue #384](https://github.com/json-c/json-c/issues/384) - Fix a VS 2015 compiler warnings. \ diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/issues_closed_for_0.14.md thunderbird-91.8.1+build1/comm/third_party/json-c/issues_closed_for_0.14.md --- thunderbird-91.7.0+build2/comm/third_party/json-c/issues_closed_for_0.14.md 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/issues_closed_for_0.14.md 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,202 @@ +This list was created with: + +``` +curl https://api.github.com/search/issues?q="repo%3Ajson-c%2Fjson-c+closed%3A>2017-12-07+created%3A<2020-04-17&sort=created&order=asc&per_page=400&page=1" > issues1.out +curl https://api.github.com/search/issues?q="repo%3Ajson-c%2Fjson-c+closed%3A>2017-12-07+created%3A<2020-04-17&sort=created&order=asc&per_page=400&page=2" > issues2.out +curl https://api.github.com/search/issues?q="repo%3Ajson-c%2Fjson-c+closed%3A>2017-12-07+created%3A<2020-04-17&sort=created&order=asc&per_page=400&page=3" > issues3.out +jq -r '.items[] | "[" + .title + "](" + .url + ")" | tostring' issues?.out > issues.md +sed -e's,^\[ *\(.*\)\](https://api.github.com/.*/\([0-9].*\)),[Issue #\2](https://github.com/json-c/json-c/issues/\2) - \1,' -i issues.md +#... manual editing ... +``` + +---- + +Issues and Pull Requests closed for the 0.14 release (since commit d582d3a(2017-12-07) to a911439(2020-04-17)) + + +* [Issue #122](https://github.com/json-c/json-c/issues/122) - Add utf-8 validation when parsing strings. \ +* [Issue #139](https://github.com/json-c/json-c/issues/139) - json_object_from_file cannot accept max_depth \ +* [Issue #143](https://github.com/json-c/json-c/issues/143) - RFE / enhancement for full 64-bit signed/unsigned support \ +* [Issue #147](https://github.com/json-c/json-c/issues/147) - Please introduce soname bump if API changed \ +* [Issue #166](https://github.com/json-c/json-c/issues/166) - Need a way to specify nesting depth when opening JSON file \ +* [Issue #226](https://github.com/json-c/json-c/issues/226) - There is no json_object_new_null() \ +* [Issue #314](https://github.com/json-c/json-c/issues/314) - new release ? \ +* [Issue #326](https://github.com/json-c/json-c/issues/326) - Please extend api json_object_get_uint64 \ +* [Issue #334](https://github.com/json-c/json-c/issues/334) - Switch json-c builds to use CMake \ +* [Issue #386](https://github.com/json-c/json-c/issues/386) - Makefile: Add ACLOCAL_AMFLAGS \ +* [Issue #387](https://github.com/json-c/json-c/issues/387) - doc: Use other doxygen feature to specify mainpage \ +* [Issue #388](https://github.com/json-c/json-c/issues/388) - json_object: Add size_t json_object_sizeof() \ +* [Issue #389](https://github.com/json-c/json-c/issues/389) - json_object: Avoid double free (and thus a segfault) when ref_count gets < 0 \ +* [Issue #390](https://github.com/json-c/json-c/issues/390) - json_object: Add const size_t json_c_object_sizeof() \ +* [Issue #391](https://github.com/json-c/json-c/issues/391) - Fix non-GNUC define for JSON_C_CONST_FUNCTION \ +* [Issue #392](https://github.com/json-c/json-c/issues/392) - json_object: Avoid invalid free (and thus a segfault) when ref_count gets < 0 \ +* [Issue #393](https://github.com/json-c/json-c/issues/393) - json_object_private: Use unsigned 32-bit integer type for refcount \ +* [Issue #394](https://github.com/json-c/json-c/issues/394) - Problem serializing double \ +* [Issue #395](https://github.com/json-c/json-c/issues/395) - Key gets modified if it contains "\" \ +* [Issue #396](https://github.com/json-c/json-c/issues/396) - Build failure with no threads uClibc toolchain \ +* [Issue #397](https://github.com/json-c/json-c/issues/397) - update json object with key. \ +* [Issue #398](https://github.com/json-c/json-c/issues/398) - Build failed. \ +* [Issue #399](https://github.com/json-c/json-c/issues/399) - Avoid uninitialized variable warnings \ +* [Issue #400](https://github.com/json-c/json-c/issues/400) - How to generate static lib (.a) \ +* [Issue #401](https://github.com/json-c/json-c/issues/401) - Warnings with Valgrind \ +* [Issue #402](https://github.com/json-c/json-c/issues/402) - Add fuzzers from OSS-Fuzz \ +* [Issue #403](https://github.com/json-c/json-c/issues/403) - Segmentation fault when double quotes is used \ +* [Issue #404](https://github.com/json-c/json-c/issues/404) - valgrind: memory leak \ +* [Issue #405](https://github.com/json-c/json-c/issues/405) - Missing API to determine an object is empty \ +* [Issue #406](https://github.com/json-c/json-c/issues/406) - Undefine NDEBUG for tests \ +* [Issue #407](https://github.com/json-c/json-c/issues/407) - json_tokener_parse is crash \ +* [Issue #408](https://github.com/json-c/json-c/issues/408) - bug in array_list_del_idx when array_list_length()==1 \ +* [Issue #410](https://github.com/json-c/json-c/issues/410) - Fixed typos \ +* [Issue #411](https://github.com/json-c/json-c/issues/411) - Crash- signal SIGSEGV, Segmentation fault. ../sysdeps/x86_64/strlen.S: No such file or directory. \ +* [Issue #412](https://github.com/json-c/json-c/issues/412) - json_type changes during inter process communication. \ +* [Issue #413](https://github.com/json-c/json-c/issues/413) - how to read object of type `json_object *` in c++ \ +* [Issue #414](https://github.com/json-c/json-c/issues/414) - [Question] How JSON-c stores the serialized data in memory? \ +* [Issue #415](https://github.com/json-c/json-c/issues/415) - Resolve windows name conflict \ +* [Issue #416](https://github.com/json-c/json-c/issues/416) - segmentation fault in json_tokener_parse \ +* [Issue #417](https://github.com/json-c/json-c/issues/417) - json_tokener_parse json_object_object_get_ex with string value which is json string \ +* [Issue #418](https://github.com/json-c/json-c/issues/418) - json_object_from_* return value documented incorrectly \ +* [Issue #419](https://github.com/json-c/json-c/issues/419) - Suggestion: document (and define) that json_object_put() accepts NULL pointer to object \ +* [Issue #420](https://github.com/json-c/json-c/issues/420) - arraylist: Fixed names of parameters for callback function \ +* [Issue #421](https://github.com/json-c/json-c/issues/421) - install json_object_iterator.h header file \ +* [Issue #422](https://github.com/json-c/json-c/issues/422) - json_object_get_double() does not set errno when there is no valid conversion \ +* [Issue #423](https://github.com/json-c/json-c/issues/423) - memory leak \ +* [Issue #424](https://github.com/json-c/json-c/issues/424) - Parse string contains "\" or "/" errors \ +* [Issue #425](https://github.com/json-c/json-c/issues/425) - what this is? \ +* [Issue #426](https://github.com/json-c/json-c/issues/426) - __deprecated not supported on clang. \ +* [Issue #427](https://github.com/json-c/json-c/issues/427) - CMake: builds involving this target will not be correct \ +* [Issue #430](https://github.com/json-c/json-c/issues/430) - json_object_object_del() and Segmentation fault \ +* [Issue #431](https://github.com/json-c/json-c/issues/431) - cmake: Bump required version \ +* [Issue #432](https://github.com/json-c/json-c/issues/432) - The real CMake support. \ +* [Issue #433](https://github.com/json-c/json-c/issues/433) - The real CMake support. \ +* [Issue #434](https://github.com/json-c/json-c/issues/434) - The real CMake support \ +* [Issue #435](https://github.com/json-c/json-c/issues/435) - json_object_object_del() segmentation fault \ +* [Issue #436](https://github.com/json-c/json-c/issues/436) - Improve pkgconfig setting \ +* [Issue #437](https://github.com/json-c/json-c/issues/437) - Bad link in README.md \ +* [Issue #438](https://github.com/json-c/json-c/issues/438) - Bad link in README.html \ +* [Issue #439](https://github.com/json-c/json-c/issues/439) - reserved identifier violation \ +* [Issue #440](https://github.com/json-c/json-c/issues/440) - Use of angle brackets around file names for include statements \ +* [Issue #441](https://github.com/json-c/json-c/issues/441) - fix c flag loss during cmake building \ +* [Issue #442](https://github.com/json-c/json-c/issues/442) - error in configure file \ +* [Issue #443](https://github.com/json-c/json-c/issues/443) - remove pretty spaces when using pretty tabs \ +* [Issue #444](https://github.com/json-c/json-c/issues/444) - Document refcount of json_tokener_parse_ex return \ +* [Issue #445](https://github.com/json-c/json-c/issues/445) - Add missing "make check" target to cmake config \ +* [Issue #446](https://github.com/json-c/json-c/issues/446) - Forward slashes get escaped \ +* [Issue #448](https://github.com/json-c/json-c/issues/448) - Buffer overflow in json-c \ +* [Issue #449](https://github.com/json-c/json-c/issues/449) - Need of json_type_int64 returned by json_object_get_type() \ +* [Issue #450](https://github.com/json-c/json-c/issues/450) - Allow use json-c cmake as subproject \ +* [Issue #452](https://github.com/json-c/json-c/issues/452) - Update README.md \ +* [Issue #453](https://github.com/json-c/json-c/issues/453) - Fixed misalignment in JSON string due to space after \n being printed... \ +* [Issue #454](https://github.com/json-c/json-c/issues/454) - json_object_private: save 8 bytes in struct json_object in 64-bit arc… \ +* [Issue #455](https://github.com/json-c/json-c/issues/455) - index.html:fix dead link \ +* [Issue #456](https://github.com/json-c/json-c/issues/456) - STYLE.txt:remove executable permissions \ +* [Issue #457](https://github.com/json-c/json-c/issues/457) - .gitignore:add build directory \ +* [Issue #458](https://github.com/json-c/json-c/issues/458) - README.md:fix dead "file.html" link \ +* [Issue #459](https://github.com/json-c/json-c/issues/459) - README.html:fix link to Doxygen docs, remove WIN32 link \ +* [Issue #460](https://github.com/json-c/json-c/issues/460) - No docs for json_object_new_string_len() \ +* [Issue #461](https://github.com/json-c/json-c/issues/461) - json_object.c:set errno in json_object_get_double() \ +* [Issue #462](https://github.com/json-c/json-c/issues/462) - json_object.h:document json_object_new_string_len() \ +* [Issue #463](https://github.com/json-c/json-c/issues/463) - please check newlocale api first argument valuse. \ +* [Issue #465](https://github.com/json-c/json-c/issues/465) - CMakeLists.txt doesn't contain json_object_iterator.h which json.h includes \ +* [Issue #466](https://github.com/json-c/json-c/issues/466) - configure:3610: error: C compiler cannot create executables \ +* [Issue #467](https://github.com/json-c/json-c/issues/467) - Fix compiler warnings \ +* [Issue #468](https://github.com/json-c/json-c/issues/468) - Fix compiler warnings \ +* [Issue #469](https://github.com/json-c/json-c/issues/469) - Build under alpine with pecl install & docker-php-ext-enable? \ +* [Issue #470](https://github.com/json-c/json-c/issues/470) - cfuhash_foreach_remove doesn't upate cfuhash_num_entries \ +* [Issue #472](https://github.com/json-c/json-c/issues/472) - Segmentation fault in json_object_iter_begin \ +* [Issue #473](https://github.com/json-c/json-c/issues/473) - Convert ChangeLog to valid UTF-8 encoding. \ +* [Issue #474](https://github.com/json-c/json-c/issues/474) - Installation directories empty with CMake in pkg-config. \ +* [Issue #475](https://github.com/json-c/json-c/issues/475) - improvement proposal for json_object_object_foreach \ +* [Issue #477](https://github.com/json-c/json-c/issues/477) - Hang/Crash with large strings \ +* [Issue #478](https://github.com/json-c/json-c/issues/478) - json_object_get_string_len returns 0 when value is number \ +* [Issue #479](https://github.com/json-c/json-c/issues/479) - I want to use it in iOS or Android but I can't compile \ +* [Issue #480](https://github.com/json-c/json-c/issues/480) - json-c-0.12.1 failed making from source code \ +* [Issue #481](https://github.com/json-c/json-c/issues/481) - error while loading shared libraries: libjson-c.so.4 \ +* [Issue #482](https://github.com/json-c/json-c/issues/482) - Error "double free or corruption" after free() \ +* [Issue #483](https://github.com/json-c/json-c/issues/483) - compatible with rarely-used Chinese characters in GBK charset \ +* [Issue #485](https://github.com/json-c/json-c/issues/485) - Install CMake module files \ +* [Issue #486](https://github.com/json-c/json-c/issues/486) - In the case of negative double value, it is formatted without including ".0" \ +* [Issue #488](https://github.com/json-c/json-c/issues/488) - Some APIs are not exported when built as shared lib on Win32 \ +* [Issue #489](https://github.com/json-c/json-c/issues/489) - Don't use -Werror by default \ +* [Issue #490](https://github.com/json-c/json-c/issues/490) - do not compile with -Werror by default \ +* [Issue #491](https://github.com/json-c/json-c/issues/491) - build: add option --disable-werror to configure \ +* [Issue #492](https://github.com/json-c/json-c/issues/492) - lack some quick usage in readme \ +* [Issue #494](https://github.com/json-c/json-c/issues/494) - Code generator? \ +* [Issue #495](https://github.com/json-c/json-c/issues/495) - README.md:fix 2 typos \ +* [Issue #496](https://github.com/json-c/json-c/issues/496) - json_pointer.h:suggest minor grammar improvement for pointer doc \ +* [Issue #497](https://github.com/json-c/json-c/issues/497) - add common header for all tests \ +* [Issue #498](https://github.com/json-c/json-c/issues/498) - double_serializer_test fails (with valgrind) \ +* [Issue #499](https://github.com/json-c/json-c/issues/499) - .travis.yml:test on more recent clang and gcc versions \ +* [Issue #500](https://github.com/json-c/json-c/issues/500) - test/Makefile.am:add missing deps for test1 and test2 \ +* [Issue #501](https://github.com/json-c/json-c/issues/501) - undefine NDEBUG for tests \ +* [Issue #502](https://github.com/json-c/json-c/issues/502) - configure error \ +* [Issue #503](https://github.com/json-c/json-c/issues/503) - json-c retuns OK when Invalid json string is passed \ +* [Issue #504](https://github.com/json-c/json-c/issues/504) - json_object_put coredump \ +* [Issue #505](https://github.com/json-c/json-c/issues/505) - Add vcpkg installation instructions \ +* [Issue #506](https://github.com/json-c/json-c/issues/506) - Cannot parse more than one object \ +* [Issue #509](https://github.com/json-c/json-c/issues/509) - Sometimes a double value is not serialized \ +* [Issue #510](https://github.com/json-c/json-c/issues/510) - Bump so-name and improve CMake \ +* [Issue #511](https://github.com/json-c/json-c/issues/511) - Reduce lines for better optimization \ +* [Issue #512](https://github.com/json-c/json-c/issues/512) - Properly append to CMAKE_C_FLAGS string \ +* [Issue #513](https://github.com/json-c/json-c/issues/513) - What does `userdata` means?And what is the case we can use it? \ +* [Issue #514](https://github.com/json-c/json-c/issues/514) - Json c 0.13 \ +* [Issue #515](https://github.com/json-c/json-c/issues/515) - Mies suomesta fixes segfaults and logic errors \ +* [Issue #516](https://github.com/json-c/json-c/issues/516) - Lja slight mods \ +* [Issue #518](https://github.com/json-c/json-c/issues/518) - Escape character "\\003\", get unexpected value \ +* [Issue #519](https://github.com/json-c/json-c/issues/519) - Add test case obj token \ +* [Issue #520](https://github.com/json-c/json-c/issues/520) - Adding type uint64 \ +* [Issue #521](https://github.com/json-c/json-c/issues/521) - build cmake windows 10 \ +* [Issue #522](https://github.com/json-c/json-c/issues/522) - update json_visit testcase \ +* [Issue #523](https://github.com/json-c/json-c/issues/523) - update tsetcase for tokener_c \ +* [Issue #524](https://github.com/json-c/json-c/issues/524) - Increase coverage \ +* [Issue #525](https://github.com/json-c/json-c/issues/525) - update pointer test case \ +* [Issue #526](https://github.com/json-c/json-c/issues/526) - Increased the test coverage of printbuf.c 82% to 92%. \ +* [Issue #527](https://github.com/json-c/json-c/issues/527) - Arraylist testcase \ +* [Issue #528](https://github.com/json-c/json-c/issues/528) - Solve issue #108. Skip \u0000 while parsing. \ +* [Issue #529](https://github.com/json-c/json-c/issues/529) - Increased the test coverage of json_c_version.c 0% to 100%. \ +* [Issue #530](https://github.com/json-c/json-c/issues/530) - validate utf-8 string before parse \ +* [Issue #531](https://github.com/json-c/json-c/issues/531) - validate utf-8 string \ +* [Issue #532](https://github.com/json-c/json-c/issues/532) - json_object_object_get_ex returning the original object \ +* [Issue #533](https://github.com/json-c/json-c/issues/533) - Fix "make check" \ +* [Issue #535](https://github.com/json-c/json-c/issues/535) - short string optimization: excessive array length \ +* [Issue #536](https://github.com/json-c/json-c/issues/536) - add json_object_new_null() \ +* [Issue #538](https://github.com/json-c/json-c/issues/538) - update shortstring and arraylist parameters \ +* [Issue #539](https://github.com/json-c/json-c/issues/539) - double serializes to the old value after set_double \ +* [Issue #541](https://github.com/json-c/json-c/issues/541) - add coveralls auto tool to json-c \ +* [Issue #542](https://github.com/json-c/json-c/issues/542) - add uint64 data to json-c \ +* [Issue #543](https://github.com/json-c/json-c/issues/543) - Readme \ +* [Issue #544](https://github.com/json-c/json-c/issues/544) - Increase distcheck target in cmake \ +* [Issue #545](https://github.com/json-c/json-c/issues/545) - add doc target in cmake \ +* [Issue #546](https://github.com/json-c/json-c/issues/546) - Add uninstall target in cmake \ +* [Issue #547](https://github.com/json-c/json-c/issues/547) - modify json-c default build type, and fix up the assert() errors in t… \ +* [Issue #548](https://github.com/json-c/json-c/issues/548) - Solve some problems about cmake build type (debug/release) \ +* [Issue #549](https://github.com/json-c/json-c/issues/549) - lib installation issues \ +* [Issue #550](https://github.com/json-c/json-c/issues/550) - Format codes with clang-format tool? \ +* [Issue #551](https://github.com/json-c/json-c/issues/551) - Allow hexadecimal number format convention parsing \ +* [Issue #553](https://github.com/json-c/json-c/issues/553) - Fix/clang ubsan \ +* [Issue #554](https://github.com/json-c/json-c/issues/554) - RFC 8259 compatibility mode \ +* [Issue #555](https://github.com/json-c/json-c/issues/555) - Format json-c with clang-format tool \ +* [Issue #556](https://github.com/json-c/json-c/issues/556) - Fixes various Wreturn-type and Wimplicit-fallthrough errors on Mingw-w64 \ +* [Issue #557](https://github.com/json-c/json-c/issues/557) - Add option in CMAKE to not build documentation \ +* [Issue #558](https://github.com/json-c/json-c/issues/558) - modify the doc target message \ +* [Issue #559](https://github.com/json-c/json-c/issues/559) - json_c_visit() not exported on Windows \ +* [Issue #560](https://github.com/json-c/json-c/issues/560) - error: implicit declaration of function '_strtoi64' \ +* [Issue #561](https://github.com/json-c/json-c/issues/561) - add the badge in README.md and test the coveralls \ +* [Issue #562](https://github.com/json-c/json-c/issues/562) - Bugfix and testcases supplements \ +* [Issue #563](https://github.com/json-c/json-c/issues/563) - Changed order of calloc args to match stdlib \ +* [Issue #564](https://github.com/json-c/json-c/issues/564) - Remove autogenerated files \ +* [Issue #565](https://github.com/json-c/json-c/issues/565) - test the CI and ignore this PR \ +* [Issue #566](https://github.com/json-c/json-c/issues/566) - add the json_types.h to Makefile.am \ +* [Issue #567](https://github.com/json-c/json-c/issues/567) - Install json_types.h with autotools build as well. \ +* [Issue #568](https://github.com/json-c/json-c/issues/568) - Adding better support to MinGW \ +* [Issue #569](https://github.com/json-c/json-c/issues/569) - Handling of -Bsymbolic-function in CMakeLists.txt is deficient \ +* [Issue #571](https://github.com/json-c/json-c/issues/571) - CMake: Bump SONAME to 5. \ +* [Issue #572](https://github.com/json-c/json-c/issues/572) - Small fixes to CMakeLists \ +* [Issue #573](https://github.com/json-c/json-c/issues/573) - Fix coveralls submission. \ +* [Issue #574](https://github.com/json-c/json-c/issues/574) - autogen.sh missing from repository \ +* [Issue #575](https://github.com/json-c/json-c/issues/575) - Small cosmetics. \ +* [Issue #576](https://github.com/json-c/json-c/issues/576) - Test coverage for json_c_version. \ +* [Issue #577](https://github.com/json-c/json-c/issues/577) - Be verbose on failing json_c_version test. \ +* [Issue #578](https://github.com/json-c/json-c/issues/578) - CMake: Install pkgconfig file in proper location by default \ +* [Issue #579](https://github.com/json-c/json-c/issues/579) - Enforce strict prototypes. \ +* [Issue #580](https://github.com/json-c/json-c/issues/580) - Fix CMake tests for enforced strict prototypes. \ +* [Issue #581](https://github.com/json-c/json-c/issues/581) - CMakeLists: do not enforce strict prototypes on Windows. \ diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_c_version.c thunderbird-91.8.1+build1/comm/third_party/json-c/json_c_version.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_c_version.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_c_version.c 2022-04-15 07:49:21.000000000 +0000 @@ -17,4 +17,3 @@ { return JSON_C_VERSION_NUM; } - diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_c_version.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_c_version.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_c_version.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_c_version.h 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012,2017 Eric Haszlakiewicz + * Copyright (c) 2012,2017,2019,2020 Eric Hawicz * * This library is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See COPYING for details. @@ -12,19 +12,30 @@ #ifndef _json_c_version_h_ #define _json_c_version_h_ +#ifdef __cplusplus +extern "C" { +#endif + #define JSON_C_MAJOR_VERSION 0 -#define JSON_C_MINOR_VERSION 13 -#define JSON_C_MICRO_VERSION 01 -#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \ - (JSON_C_MINOR_VERSION << 8) | \ - JSON_C_MICRO_VERSION) -#define JSON_C_VERSION "0.13.1" +#define JSON_C_MINOR_VERSION 15 +#define JSON_C_MICRO_VERSION 0 +#define JSON_C_VERSION_NUM \ + ((JSON_C_MAJOR_VERSION << 16) | (JSON_C_MINOR_VERSION << 8) | JSON_C_MICRO_VERSION) +#define JSON_C_VERSION "0.15" + +#ifndef JSON_EXPORT +#if defined(_MSC_VER) +#define JSON_EXPORT __declspec(dllexport) +#else +#define JSON_EXPORT extern +#endif +#endif /** * @see JSON_C_VERSION * @return the version of the json-c library as a string */ -const char *json_c_version(void); /* Returns JSON_C_VERSION */ +JSON_EXPORT const char *json_c_version(void); /* Returns JSON_C_VERSION */ /** * The json-c version encoded into an int, with the low order 8 bits @@ -35,6 +46,10 @@ * @see JSON_C_VERSION_NUM * @return the version of the json-c library as an int */ -int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */ +JSON_EXPORT int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */ + +#ifdef __cplusplus +} +#endif #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json.h thunderbird-91.8.1+build1/comm/third_party/json-c/json.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json.h 2022-04-15 07:49:21.000000000 +0000 @@ -21,15 +21,15 @@ extern "C" { #endif -#include "debug.h" -#include "linkhash.h" #include "arraylist.h" -#include "json_util.h" +#include "debug.h" +#include "json_c_version.h" #include "json_object.h" +#include "json_object_iterator.h" #include "json_pointer.h" #include "json_tokener.h" -#include "json_object_iterator.h" -#include "json_c_version.h" +#include "json_util.h" +#include "linkhash.h" #ifdef __cplusplus } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_inttypes.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_inttypes.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_inttypes.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_inttypes.h 2022-04-15 07:49:21.000000000 +0000 @@ -17,6 +17,7 @@ #define PRId64 "I64d" #define SCNd64 "I64d" +#define PRIu64 "I64u" #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_object.c thunderbird-91.8.1+build1/comm/third_party/json-c/json_object.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_object.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_object.c 2022-04-15 07:49:22.000000000 +0000 @@ -1,6 +1,4 @@ /* - * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $ - * * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. * Michael Clark * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. @@ -16,36 +14,123 @@ #include #include +#ifdef HAVE_LIMITS_H +#include +#endif +#include +#include #include #include -#include #include -#include -#include "debug.h" -#include "printbuf.h" -#include "linkhash.h" #include "arraylist.h" +#include "debug.h" #include "json_inttypes.h" #include "json_object.h" #include "json_object_private.h" #include "json_util.h" +#include "linkhash.h" #include "math_compat.h" -#include "strdup_compat.h" +#include "printbuf.h" #include "snprintf_compat.h" +#include "strdup_compat.h" #if SIZEOF_LONG_LONG != SIZEOF_INT64_T #error "The long long type isn't 64-bits" #endif +#ifndef SSIZE_T_MAX +#if SIZEOF_SSIZE_T == SIZEOF_INT +#define SSIZE_T_MAX INT_MAX +#elif SIZEOF_SSIZE_T == SIZEOF_LONG +#define SSIZE_T_MAX LONG_MAX +#elif SIZEOF_SSIZE_T == SIZEOF_LONG_LONG +#define SSIZE_T_MAX LLONG_MAX +#else +#error Unable to determine size of ssize_t +#endif +#endif + // Don't define this. It's not thread-safe. /* #define REFCOUNT_DEBUG 1 */ -const char *json_number_chars = "0123456789.+-eE"; const char *json_hex_chars = "0123456789abcdefABCDEF"; -static void json_object_generic_delete(struct json_object* jso); -static struct json_object* json_object_new(enum json_type o_type); +static void json_object_generic_delete(struct json_object *jso); + +#if defined(_MSC_VER) && (_MSC_VER <= 1800) +/* VS2013 doesn't know about "inline" */ +#define inline __inline +#elif defined(AIX_CC) +#define inline +#endif + +/* + * Helper functions to more safely cast to a particular type of json_object + */ +static inline struct json_object_object *JC_OBJECT(struct json_object *jso) +{ + return (void *)jso; +} +static inline const struct json_object_object *JC_OBJECT_C(const struct json_object *jso) +{ + return (const void *)jso; +} +static inline struct json_object_array *JC_ARRAY(struct json_object *jso) +{ + return (void *)jso; +} +static inline const struct json_object_array *JC_ARRAY_C(const struct json_object *jso) +{ + return (const void *)jso; +} +static inline struct json_object_boolean *JC_BOOL(struct json_object *jso) +{ + return (void *)jso; +} +static inline const struct json_object_boolean *JC_BOOL_C(const struct json_object *jso) +{ + return (const void *)jso; +} +static inline struct json_object_double *JC_DOUBLE(struct json_object *jso) +{ + return (void *)jso; +} +static inline const struct json_object_double *JC_DOUBLE_C(const struct json_object *jso) +{ + return (const void *)jso; +} +static inline struct json_object_int *JC_INT(struct json_object *jso) +{ + return (void *)jso; +} +static inline const struct json_object_int *JC_INT_C(const struct json_object *jso) +{ + return (const void *)jso; +} +static inline struct json_object_string *JC_STRING(struct json_object *jso) +{ + return (void *)jso; +} +static inline const struct json_object_string *JC_STRING_C(const struct json_object *jso) +{ + return (const void *)jso; +} + +#define JC_CONCAT(a, b) a##b +#define JC_CONCAT3(a, b, c) a##b##c + +#define JSON_OBJECT_NEW(jtype) \ + (struct JC_CONCAT(json_object_, jtype) *)json_object_new( \ + JC_CONCAT(json_type_, jtype), sizeof(struct JC_CONCAT(json_object_, jtype)), \ + &JC_CONCAT3(json_object_, jtype, _to_json_string)) + +static inline struct json_object *json_object_new(enum json_type o_type, size_t alloc_size, + json_object_to_json_string_fn *to_json_string); + +static void json_object_object_delete(struct json_object *jso_base); +static void json_object_string_delete(struct json_object *jso); +static void json_object_array_delete(struct json_object *jso); static json_object_to_json_string_fn json_object_object_to_json_string; static json_object_to_json_string_fn json_object_boolean_to_json_string; @@ -53,7 +138,26 @@ static json_object_to_json_string_fn json_object_int_to_json_string; static json_object_to_json_string_fn json_object_string_to_json_string; static json_object_to_json_string_fn json_object_array_to_json_string; +static json_object_to_json_string_fn _json_object_userdata_to_json_string; +#ifndef JSON_NORETURN +#if defined(_MSC_VER) +#define JSON_NORETURN __declspec(noreturn) +#elif defined(__OS400__) +#define JSON_NORETURN +#else +/* 'cold' attribute is for optimization, telling the computer this code + * path is unlikely. + */ +#define JSON_NORETURN __attribute__((noreturn, cold)) +#endif +#endif +/** + * Abort and optionally print a message on standard error. + * This should be used rather than assert() for unconditional abortion + * (in particular for code paths which are never supposed to be run). + * */ +JSON_NORETURN static void json_abort(const char *message); /* ref count debugging */ @@ -61,13 +165,14 @@ static struct lh_table *json_object_table; -static void json_object_init(void) __attribute__ ((constructor)); -static void json_object_init(void) { +static void json_object_init(void) __attribute__((constructor)); +static void json_object_init(void) +{ MC_DEBUG("json_object_init: creating object table\n"); json_object_table = lh_kptr_table_new(128, NULL); } -static void json_object_fini(void) __attribute__ ((destructor)); +static void json_object_fini(void) __attribute__((destructor)); static void json_object_fini(void) { struct lh_entry *ent; @@ -76,13 +181,11 @@ if (json_object_table->count) { MC_DEBUG("json_object_fini: %d referenced objects at exit\n", - json_object_table->count); + json_object_table->count); lh_foreach(json_object_table, ent) { - struct json_object* obj = - (struct json_object*) lh_entry_v(ent); - MC_DEBUG("\t%s:%p\n", - json_type_to_name(obj->o_type), obj); + struct json_object *obj = (struct json_object *)lh_entry_v(ent); + MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj); } } } @@ -91,26 +194,32 @@ } #endif /* REFCOUNT_DEBUG */ - /* helper for accessing the optimized string data component in json_object */ -static const char * -get_string_component(const struct json_object *jso) +static inline char *get_string_component_mutable(struct json_object *jso) +{ + if (JC_STRING_C(jso)->len < 0) + { + /* Due to json_object_set_string(), we might have a pointer */ + return JC_STRING(jso)->c_string.pdata; + } + return JC_STRING(jso)->c_string.idata; +} +static inline const char *get_string_component(const struct json_object *jso) { - return (jso->o.c_string.len < LEN_DIRECT_STRING_DATA) ? - jso->o.c_string.str.data : jso->o.c_string.str.ptr; + return get_string_component_mutable((void *)(uintptr_t)(const void *)jso); } /* string escaping */ -static int json_escape_str(struct printbuf *pb, const char *str, int len, int flags) +static int json_escape_str(struct printbuf *pb, const char *str, size_t len, int flags) { int pos = 0, start_offset = 0; unsigned char c; while (len--) { c = str[pos]; - switch(c) + switch (c) { case '\b': case '\n': @@ -120,41 +229,47 @@ case '"': case '\\': case '/': - if((flags & JSON_C_TO_STRING_NOSLASHESCAPE) && c == '/') + if ((flags & JSON_C_TO_STRING_NOSLASHESCAPE) && c == '/') { pos++; break; } - if(pos - start_offset > 0) + if (pos - start_offset > 0) printbuf_memappend(pb, str + start_offset, pos - start_offset); - if(c == '\b') printbuf_memappend(pb, "\\b", 2); - else if(c == '\n') printbuf_memappend(pb, "\\n", 2); - else if(c == '\r') printbuf_memappend(pb, "\\r", 2); - else if(c == '\t') printbuf_memappend(pb, "\\t", 2); - else if(c == '\f') printbuf_memappend(pb, "\\f", 2); - else if(c == '"') printbuf_memappend(pb, "\\\"", 2); - else if(c == '\\') printbuf_memappend(pb, "\\\\", 2); - else if(c == '/') printbuf_memappend(pb, "\\/", 2); + if (c == '\b') + printbuf_memappend(pb, "\\b", 2); + else if (c == '\n') + printbuf_memappend(pb, "\\n", 2); + else if (c == '\r') + printbuf_memappend(pb, "\\r", 2); + else if (c == '\t') + printbuf_memappend(pb, "\\t", 2); + else if (c == '\f') + printbuf_memappend(pb, "\\f", 2); + else if (c == '"') + printbuf_memappend(pb, "\\\"", 2); + else if (c == '\\') + printbuf_memappend(pb, "\\\\", 2); + else if (c == '/') + printbuf_memappend(pb, "\\/", 2); start_offset = ++pos; break; default: - if(c < ' ') + if (c < ' ') { char sbuf[7]; - if(pos - start_offset > 0) - printbuf_memappend(pb, - str + start_offset, - pos - start_offset); - snprintf(sbuf, sizeof(sbuf), - "\\u00%c%c", - json_hex_chars[c >> 4], - json_hex_chars[c & 0xf]); - printbuf_memappend_fast(pb, sbuf, (int) sizeof(sbuf) - 1); + if (pos - start_offset > 0) + printbuf_memappend(pb, str + start_offset, + pos - start_offset); + snprintf(sbuf, sizeof(sbuf), "\\u00%c%c", json_hex_chars[c >> 4], + json_hex_chars[c & 0xf]); + printbuf_memappend_fast(pb, sbuf, (int)sizeof(sbuf) - 1); start_offset = ++pos; - } else + } + else pos++; } } @@ -163,25 +278,29 @@ return 0; } - /* reference counting */ -extern struct json_object* json_object_get(struct json_object *jso) +struct json_object *json_object_get(struct json_object *jso) { - if (!jso) return jso; + if (!jso) + return jso; + + // Don't overflow the refcounter. + assert(jso->_ref_count < UINT32_MAX); #if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING) __sync_add_and_fetch(&jso->_ref_count, 1); #else ++jso->_ref_count; -#endif +#endif return jso; } int json_object_put(struct json_object *jso) { - if(!jso) return 0; + if (!jso) + return 0; /* Avoid invalid free and crash explicitly instead of (silently) * segfaulting. @@ -190,46 +309,59 @@ #if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING) /* Note: this only allow the refcount to remain correct - * when multiple threads are adjusting it. It is still an error + * when multiple threads are adjusting it. It is still an error * for a thread to decrement the refcount if it doesn't "own" it, * as that can result in the thread that loses the race to 0 * operating on an already-freed object. */ - if (__sync_sub_and_fetch(&jso->_ref_count, 1) > 0) return 0; + if (__sync_sub_and_fetch(&jso->_ref_count, 1) > 0) + return 0; #else - if (--jso->_ref_count > 0) return 0; + if (--jso->_ref_count > 0) + return 0; #endif if (jso->_user_delete) jso->_user_delete(jso, jso->_userdata); - jso->_delete(jso); + switch (jso->o_type) + { + case json_type_object: json_object_object_delete(jso); break; + case json_type_array: json_object_array_delete(jso); break; + case json_type_string: json_object_string_delete(jso); break; + default: json_object_generic_delete(jso); break; + } return 1; } - /* generic object construction and destruction parts */ -static void json_object_generic_delete(struct json_object* jso) +static void json_object_generic_delete(struct json_object *jso) { #ifdef REFCOUNT_DEBUG - MC_DEBUG("json_object_delete_%s: %p\n", - json_type_to_name(jso->o_type), jso); + MC_DEBUG("json_object_delete_%s: %p\n", json_type_to_name(jso->o_type), jso); lh_table_delete(json_object_table, jso); #endif /* REFCOUNT_DEBUG */ printbuf_free(jso->_pb); free(jso); } -static struct json_object* json_object_new(enum json_type o_type) +static inline struct json_object *json_object_new(enum json_type o_type, size_t alloc_size, + json_object_to_json_string_fn *to_json_string) { struct json_object *jso; - jso = (struct json_object*)calloc(sizeof(struct json_object), 1); + jso = (struct json_object *)malloc(alloc_size); if (!jso) return NULL; + jso->o_type = o_type; jso->_ref_count = 1; - jso->_delete = &json_object_generic_delete; + jso->_to_json_string = to_json_string; + jso->_pb = NULL; + jso->_user_delete = NULL; + jso->_userdata = NULL; + //jso->... // Type-specific fields must be set by caller + #ifdef REFCOUNT_DEBUG lh_table_insert(json_object_table, jso, jso); MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso); @@ -237,7 +369,6 @@ return jso; } - /* type checking functions */ int json_object_is_type(const struct json_object *jso, enum json_type type) @@ -254,12 +385,12 @@ return jso->o_type; } -void* json_object_get_userdata(json_object *jso) { +void *json_object_get_userdata(json_object *jso) +{ return jso ? jso->_userdata : NULL; } -void json_object_set_userdata(json_object *jso, void *userdata, - json_object_delete_fn *user_delete) +void json_object_set_userdata(json_object *jso, void *userdata, json_object_delete_fn *user_delete) { // Can't return failure, so abort if we can't perform the operation. assert(jso != NULL); @@ -274,30 +405,24 @@ /* set a custom conversion to string */ -void json_object_set_serializer(json_object *jso, - json_object_to_json_string_fn *to_string_func, - void *userdata, - json_object_delete_fn *user_delete) +void json_object_set_serializer(json_object *jso, json_object_to_json_string_fn *to_string_func, + void *userdata, json_object_delete_fn *user_delete) { json_object_set_userdata(jso, userdata, user_delete); if (to_string_func == NULL) { // Reset to the standard serialization function - switch(jso->o_type) + switch (jso->o_type) { - case json_type_null: - jso->_to_json_string = NULL; - break; + case json_type_null: jso->_to_json_string = NULL; break; case json_type_boolean: jso->_to_json_string = &json_object_boolean_to_json_string; break; case json_type_double: jso->_to_json_string = &json_object_double_to_json_string_default; break; - case json_type_int: - jso->_to_json_string = &json_object_int_to_json_string; - break; + case json_type_int: jso->_to_json_string = &json_object_int_to_json_string; break; case json_type_object: jso->_to_json_string = &json_object_object_to_json_string; break; @@ -314,10 +439,9 @@ jso->_to_json_string = to_string_func; } - /* extended conversion to string */ -const char* json_object_to_json_string_length(struct json_object *jso, int flags, size_t *length) +const char *json_object_to_json_string_length(struct json_object *jso, int flags, size_t *length) { const char *r = NULL; size_t s = 0; @@ -331,7 +455,7 @@ { printbuf_reset(jso->_pb); - if(jso->_to_json_string(jso, jso->_pb, 0, flags) >= 0) + if (jso->_to_json_string(jso, jso->_pb, 0, flags) >= 0) { s = (size_t)jso->_pb->bpos; r = jso->_pb->buf; @@ -343,14 +467,14 @@ return r; } -const char* json_object_to_json_string_ext(struct json_object *jso, int flags) +const char *json_object_to_json_string_ext(struct json_object *jso, int flags) { return json_object_to_json_string_length(jso, flags, NULL); } /* backwards-compatible conversion to string */ -const char* json_object_to_json_string(struct json_object *jso) +const char *json_object_to_json_string(struct json_object *jso) { return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED); } @@ -372,10 +496,8 @@ /* json_object_object */ -static int json_object_object_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, - int flags) +static int json_object_object_to_json_string(struct json_object *jso, struct printbuf *pb, + int level, int flags) { int had_children = 0; struct json_object_iter iter; @@ -392,82 +514,74 @@ printbuf_strappend(pb, "\n"); } had_children = 1; - if (flags & JSON_C_TO_STRING_SPACED) + if (flags & JSON_C_TO_STRING_SPACED && !(flags & JSON_C_TO_STRING_PRETTY)) printbuf_strappend(pb, " "); - indent(pb, level+1, flags); + indent(pb, level + 1, flags); printbuf_strappend(pb, "\""); json_escape_str(pb, iter.key, strlen(iter.key), flags); if (flags & JSON_C_TO_STRING_SPACED) printbuf_strappend(pb, "\": "); else printbuf_strappend(pb, "\":"); - if(iter.val == NULL) + if (iter.val == NULL) printbuf_strappend(pb, "null"); - else - if (iter.val->_to_json_string(iter.val, pb, level+1,flags) < 0) - return -1; + else if (iter.val->_to_json_string(iter.val, pb, level + 1, flags) < 0) + return -1; } if (flags & JSON_C_TO_STRING_PRETTY) { if (had_children) printbuf_strappend(pb, "\n"); - indent(pb,level,flags); + indent(pb, level, flags); } - if (flags & JSON_C_TO_STRING_SPACED) + if (flags & JSON_C_TO_STRING_SPACED && !(flags & JSON_C_TO_STRING_PRETTY)) return printbuf_strappend(pb, /*{*/ " }"); else return printbuf_strappend(pb, /*{*/ "}"); } - static void json_object_lh_entry_free(struct lh_entry *ent) { if (!ent->k_is_constant) free(lh_entry_k(ent)); - json_object_put((struct json_object*)lh_entry_v(ent)); + json_object_put((struct json_object *)lh_entry_v(ent)); } -static void json_object_object_delete(struct json_object* jso) +static void json_object_object_delete(struct json_object *jso_base) { - lh_table_free(jso->o.c_object); - json_object_generic_delete(jso); + lh_table_free(JC_OBJECT(jso_base)->c_object); + json_object_generic_delete(jso_base); } -struct json_object* json_object_new_object(void) +struct json_object *json_object_new_object(void) { - struct json_object *jso = json_object_new(json_type_object); + struct json_object_object *jso = JSON_OBJECT_NEW(object); if (!jso) return NULL; - jso->_delete = &json_object_object_delete; - jso->_to_json_string = &json_object_object_to_json_string; - jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, - &json_object_lh_entry_free); - if (!jso->o.c_object) + jso->c_object = + lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, &json_object_lh_entry_free); + if (!jso->c_object) { - json_object_generic_delete(jso); + json_object_generic_delete(&jso->base); errno = ENOMEM; return NULL; } - return jso; + return &jso->base; } -struct lh_table* json_object_get_object(const struct json_object *jso) +struct lh_table *json_object_get_object(const struct json_object *jso) { if (!jso) return NULL; - switch(jso->o_type) + switch (jso->o_type) { - case json_type_object: - return jso->o.c_object; - default: - return NULL; + case json_type_object: return JC_OBJECT_C(jso)->c_object; + default: return NULL; } } -int json_object_object_add_ex(struct json_object* jso, - const char *const key, - struct json_object *const val, - const unsigned opts) +int json_object_object_add_ex(struct json_object *jso, const char *const key, + struct json_object *const val, const unsigned opts) { struct json_object *existing_value = NULL; struct lh_entry *existing_entry; @@ -477,10 +591,11 @@ // We lookup the entry and replace the value, rather than just deleting // and re-adding it, so the existing key remains valid. - hash = lh_get_hash(jso->o.c_object, (const void *)key); - existing_entry = (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW) ? NULL : - lh_table_lookup_entry_w_hash(jso->o.c_object, - (const void *)key, hash); + hash = lh_get_hash(JC_OBJECT(jso)->c_object, (const void *)key); + existing_entry = + (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW) + ? NULL + : lh_table_lookup_entry_w_hash(JC_OBJECT(jso)->c_object, (const void *)key, hash); // The caller must avoid creating loops in the object tree, but do a // quick check anyway to make sure we're not creating a trivial loop. @@ -489,30 +604,28 @@ if (!existing_entry) { - const void *const k = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ? - (const void *)key : strdup(key); + const void *const k = + (opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ? (const void *)key : strdup(key); if (k == NULL) return -1; - return lh_table_insert_w_hash(jso->o.c_object, k, val, hash, opts); + return lh_table_insert_w_hash(JC_OBJECT(jso)->c_object, k, val, hash, opts); } - existing_value = (json_object *) lh_entry_v(existing_entry); + existing_value = (json_object *)lh_entry_v(existing_entry); if (existing_value) json_object_put(existing_value); existing_entry->v = val; return 0; } -int json_object_object_add(struct json_object* jso, const char *key, - struct json_object *val) +int json_object_object_add(struct json_object *jso, const char *key, struct json_object *val) { return json_object_object_add_ex(jso, key, val, 0); } - int json_object_object_length(const struct json_object *jso) { assert(json_object_get_type(jso) == json_type_object); - return lh_table_length(jso->o.c_object); + return lh_table_length(JC_OBJECT_C(jso)->c_object); } size_t json_c_object_sizeof(void) @@ -520,171 +633,186 @@ return sizeof(struct json_object); } -struct json_object* json_object_object_get(const struct json_object* jso, - const char *key) +struct json_object *json_object_object_get(const struct json_object *jso, const char *key) { struct json_object *result = NULL; json_object_object_get_ex(jso, key, &result); return result; } -json_bool json_object_object_get_ex(const struct json_object* jso, const char *key, - struct json_object **value) +json_bool json_object_object_get_ex(const struct json_object *jso, const char *key, + struct json_object **value) { if (value != NULL) *value = NULL; if (NULL == jso) - return FALSE; + return 0; - switch(jso->o_type) + switch (jso->o_type) { case json_type_object: - return lh_table_lookup_ex(jso->o.c_object, (const void *) key, - (void**) value); + return lh_table_lookup_ex(JC_OBJECT_C(jso)->c_object, (const void *)key, + (void **)value); default: if (value != NULL) *value = NULL; - return FALSE; + return 0; } } -void json_object_object_del(struct json_object* jso, const char *key) +void json_object_object_del(struct json_object *jso, const char *key) { assert(json_object_get_type(jso) == json_type_object); - lh_table_delete(jso->o.c_object, key); + lh_table_delete(JC_OBJECT(jso)->c_object, key); } - /* json_object_boolean */ -static int json_object_boolean_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, - int flags) +static int json_object_boolean_to_json_string(struct json_object *jso, struct printbuf *pb, + int level, int flags) { - if (jso->o.c_boolean) + if (JC_BOOL(jso)->c_boolean) return printbuf_strappend(pb, "true"); return printbuf_strappend(pb, "false"); } -struct json_object* json_object_new_boolean(json_bool b) +struct json_object *json_object_new_boolean(json_bool b) { - struct json_object *jso = json_object_new(json_type_boolean); + struct json_object_boolean *jso = JSON_OBJECT_NEW(boolean); if (!jso) return NULL; - jso->_to_json_string = &json_object_boolean_to_json_string; - jso->o.c_boolean = b; - return jso; + jso->c_boolean = b; + return &jso->base; } json_bool json_object_get_boolean(const struct json_object *jso) { if (!jso) - return FALSE; - switch(jso->o_type) + return 0; + switch (jso->o_type) { - case json_type_boolean: - return jso->o.c_boolean; + case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; case json_type_int: - return (jso->o.c_int64 != 0); - case json_type_double: - return (jso->o.c_double != 0); - case json_type_string: - return (jso->o.c_string.len != 0); - default: - return FALSE; + switch (JC_INT_C(jso)->cint_type) + { + case json_object_int_type_int64: return (JC_INT_C(jso)->cint.c_int64 != 0); + case json_object_int_type_uint64: return (JC_INT_C(jso)->cint.c_uint64 != 0); + default: json_abort("invalid cint_type"); + } + case json_type_double: return (JC_DOUBLE_C(jso)->c_double != 0); + case json_type_string: return (JC_STRING_C(jso)->len != 0); + default: return 0; } } -int json_object_set_boolean(struct json_object *jso,json_bool new_value){ - if (!jso || jso->o_type!=json_type_boolean) +int json_object_set_boolean(struct json_object *jso, json_bool new_value) +{ + if (!jso || jso->o_type != json_type_boolean) return 0; - jso->o.c_boolean=new_value; + JC_BOOL(jso)->c_boolean = new_value; return 1; } - /* json_object_int */ -static int json_object_int_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, - int flags) +static int json_object_int_to_json_string(struct json_object *jso, struct printbuf *pb, int level, + int flags) { /* room for 19 digits, the sign char, and a null term */ char sbuf[21]; - snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int64); - return printbuf_memappend (pb, sbuf, strlen(sbuf)); + if (JC_INT(jso)->cint_type == json_object_int_type_int64) + snprintf(sbuf, sizeof(sbuf), "%" PRId64, JC_INT(jso)->cint.c_int64); + else + snprintf(sbuf, sizeof(sbuf), "%" PRIu64, JC_INT(jso)->cint.c_uint64); + return printbuf_memappend(pb, sbuf, strlen(sbuf)); } -struct json_object* json_object_new_int(int32_t i) +struct json_object *json_object_new_int(int32_t i) { - struct json_object *jso = json_object_new(json_type_int); - if (!jso) - return NULL; - jso->_to_json_string = &json_object_int_to_json_string; - jso->o.c_int64 = i; - return jso; + return json_object_new_int64(i); } int32_t json_object_get_int(const struct json_object *jso) { - int64_t cint64; - enum json_type o_type; + int64_t cint64=0; + double cdouble; + enum json_type o_type; - if(!jso) return 0; + if (!jso) + return 0; + + o_type = jso->o_type; + if (o_type == json_type_int) + { + const struct json_object_int *jsoint = JC_INT_C(jso); + if (jsoint->cint_type == json_object_int_type_int64) + { + cint64 = jsoint->cint.c_int64; + } + else + { + if (jsoint->cint.c_uint64 >= INT64_MAX) + cint64 = INT64_MAX; + else + cint64 = (int64_t)jsoint->cint.c_uint64; + } + } + else if (o_type == json_type_string) + { + /* + * Parse strings into 64-bit numbers, then use the + * 64-to-32-bit number handling below. + */ + if (json_parse_int64(get_string_component(jso), &cint64) != 0) + return 0; /* whoops, it didn't work. */ + o_type = json_type_int; + } - o_type = jso->o_type; - cint64 = jso->o.c_int64; + switch (o_type) + { + case json_type_int: + /* Make sure we return the correct values for out of range numbers. */ + if (cint64 <= INT32_MIN) + return INT32_MIN; + if (cint64 >= INT32_MAX) + return INT32_MAX; + return (int32_t)cint64; + case json_type_double: + cdouble = JC_DOUBLE_C(jso)->c_double; + if (cdouble <= INT32_MIN) + return INT32_MIN; + if (cdouble >= INT32_MAX) + return INT32_MAX; + return (int32_t)cdouble; + case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; + default: return 0; + } +} - if (o_type == json_type_string) - { - /* - * Parse strings into 64-bit numbers, then use the - * 64-to-32-bit number handling below. - */ - if (json_parse_int64(get_string_component(jso), &cint64) != 0) - return 0; /* whoops, it didn't work. */ - o_type = json_type_int; - } - - switch(o_type) { - case json_type_int: - /* Make sure we return the correct values for out of range numbers. */ - if (cint64 <= INT32_MIN) - return INT32_MIN; - if (cint64 >= INT32_MAX) - return INT32_MAX; - return (int32_t) cint64; - case json_type_double: - if (jso->o.c_double <= INT32_MIN) - return INT32_MIN; - if (jso->o.c_double >= INT32_MAX) - return INT32_MAX; - return (int32_t)jso->o.c_double; - case json_type_boolean: - return jso->o.c_boolean; - default: - return 0; - } +int json_object_set_int(struct json_object *jso, int new_value) +{ + return json_object_set_int64(jso, (int64_t)new_value); } -int json_object_set_int(struct json_object *jso,int new_value){ - if (!jso || jso->o_type!=json_type_int) - return 0; - jso->o.c_int64=new_value; - return 1; +struct json_object *json_object_new_int64(int64_t i) +{ + struct json_object_int *jso = JSON_OBJECT_NEW(int); + if (!jso) + return NULL; + jso->cint.c_int64 = i; + jso->cint_type = json_object_int_type_int64; + return &jso->base; } -struct json_object* json_object_new_int64(int64_t i) +struct json_object *json_object_new_uint64(uint64_t i) { - struct json_object *jso = json_object_new(json_type_int); + struct json_object_int *jso = JSON_OBJECT_NEW(int); if (!jso) return NULL; - jso->_to_json_string = &json_object_int_to_json_string; - jso->o.c_int64 = i; - return jso; + jso->cint.c_uint64 = i; + jso->cint_type = json_object_int_type_uint64; + return &jso->base; } int64_t json_object_get_int64(const struct json_object *jso) @@ -693,47 +821,140 @@ if (!jso) return 0; - switch(jso->o_type) + switch (jso->o_type) { case json_type_int: - return jso->o.c_int64; + { + const struct json_object_int *jsoint = JC_INT_C(jso); + switch (jsoint->cint_type) + { + case json_object_int_type_int64: return jsoint->cint.c_int64; + case json_object_int_type_uint64: + if (jsoint->cint.c_uint64 >= INT64_MAX) + return INT64_MAX; + return (int64_t)jsoint->cint.c_uint64; + default: json_abort("invalid cint_type"); + } + } case json_type_double: - if (jso->o.c_double >= INT64_MAX) + // INT64_MAX can't be exactly represented as a double + // so cast to tell the compiler it's ok to round up. + if (JC_DOUBLE_C(jso)->c_double >= (double)INT64_MAX) return INT64_MAX; - if (jso->o.c_double <= INT64_MIN) + if (JC_DOUBLE_C(jso)->c_double <= INT64_MIN) return INT64_MIN; - return (int64_t)jso->o.c_double; - case json_type_boolean: - return jso->o.c_boolean; + return (int64_t)JC_DOUBLE_C(jso)->c_double; + case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; case json_type_string: if (json_parse_int64(get_string_component(jso), &cint) == 0) return cint; /* FALLTHRU */ - default: + default: return 0; + } +} + +uint64_t json_object_get_uint64(const struct json_object *jso) +{ + uint64_t cuint; + + if (!jso) return 0; + switch (jso->o_type) + { + case json_type_int: + { + const struct json_object_int *jsoint = JC_INT_C(jso); + switch (jsoint->cint_type) + { + case json_object_int_type_int64: + if (jsoint->cint.c_int64 < 0) + return 0; + return (uint64_t)jsoint->cint.c_int64; + case json_object_int_type_uint64: return jsoint->cint.c_uint64; + default: json_abort("invalid cint_type"); + } + } + case json_type_double: + // UINT64_MAX can't be exactly represented as a double + // so cast to tell the compiler it's ok to round up. + if (JC_DOUBLE_C(jso)->c_double >= (double)UINT64_MAX) + return UINT64_MAX; + if (JC_DOUBLE_C(jso)->c_double < 0) + return 0; + return (uint64_t)JC_DOUBLE_C(jso)->c_double; + case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; + case json_type_string: + if (json_parse_uint64(get_string_component(jso), &cuint) == 0) + return cuint; + /* FALLTHRU */ + default: return 0; } } -int json_object_set_int64(struct json_object *jso,int64_t new_value){ - if (!jso || jso->o_type!=json_type_int) +int json_object_set_int64(struct json_object *jso, int64_t new_value) +{ + if (!jso || jso->o_type != json_type_int) return 0; - jso->o.c_int64=new_value; + JC_INT(jso)->cint.c_int64 = new_value; + JC_INT(jso)->cint_type = json_object_int_type_int64; return 1; } -int json_object_int_inc(struct json_object *jso, int64_t val) { +int json_object_set_uint64(struct json_object *jso, uint64_t new_value) +{ if (!jso || jso->o_type != json_type_int) return 0; - if (val > 0 && jso->o.c_int64 > INT64_MAX - val) { - jso->o.c_int64 = INT64_MAX; - } else if (val < 0 && jso->o.c_int64 < INT64_MIN - val) { - jso->o.c_int64 = INT64_MIN; - } else { - jso->o.c_int64 += val; - } + JC_INT(jso)->cint.c_uint64 = new_value; + JC_INT(jso)->cint_type = json_object_int_type_uint64; return 1; } +int json_object_int_inc(struct json_object *jso, int64_t val) +{ + struct json_object_int *jsoint; + if (!jso || jso->o_type != json_type_int) + return 0; + jsoint = JC_INT(jso); + switch (jsoint->cint_type) + { + case json_object_int_type_int64: + if (val > 0 && jsoint->cint.c_int64 > INT64_MAX - val) + { + jsoint->cint.c_uint64 = (uint64_t)jsoint->cint.c_int64 + (uint64_t)val; + jsoint->cint_type = json_object_int_type_uint64; + } + else if (val < 0 && jsoint->cint.c_int64 < INT64_MIN - val) + { + jsoint->cint.c_int64 = INT64_MIN; + } + else + { + jsoint->cint.c_int64 += val; + } + return 1; + case json_object_int_type_uint64: + if (val > 0 && jsoint->cint.c_uint64 > UINT64_MAX - (uint64_t)val) + { + jsoint->cint.c_uint64 = UINT64_MAX; + } + else if (val < 0 && jsoint->cint.c_uint64 < (uint64_t)(-val)) + { + jsoint->cint.c_int64 = (int64_t)jsoint->cint.c_uint64 + val; + jsoint->cint_type = json_object_int_type_int64; + } + else if (val < 0 && jsoint->cint.c_uint64 >= (uint64_t)(-val)) + { + jsoint->cint.c_uint64 -= (uint64_t)(-val); + } + else + { + jsoint->cint.c_uint64 += val; + } + return 1; + default: json_abort("invalid cint_type"); + } +} + /* json_object_double */ #if defined(HAVE___THREAD) @@ -773,32 +994,31 @@ } else { - _json_c_set_last_err("json_c_set_option: invalid global_or_thread value: %d\n", global_or_thread); + _json_c_set_last_err("json_c_set_option: invalid global_or_thread value: %d\n", + global_or_thread); return -1; } return 0; } - -static int json_object_double_to_json_string_format(struct json_object* jso, - struct printbuf *pb, - int level, - int flags, - const char *format) +static int json_object_double_to_json_string_format(struct json_object *jso, struct printbuf *pb, + int level, int flags, const char *format) { + struct json_object_double *jsodbl = JC_DOUBLE(jso); char buf[128], *p, *q; int size; /* Although JSON RFC does not support - NaN or Infinity as numeric values - ECMA 262 section 9.8.1 defines - how to handle these cases as strings */ - if (isnan(jso->o.c_double)) + * NaN or Infinity as numeric values + * ECMA 262 section 9.8.1 defines + * how to handle these cases as strings + */ + if (isnan(jsodbl->c_double)) { size = snprintf(buf, sizeof(buf), "NaN"); } - else if (isinf(jso->o.c_double)) + else if (isinf(jsodbl->c_double)) { - if(jso->o.c_double > 0) + if (jsodbl->c_double > 0) size = snprintf(buf, sizeof(buf), "Infinity"); else size = snprintf(buf, sizeof(buf), "-Infinity"); @@ -807,6 +1027,7 @@ { const char *std_format = "%.17g"; int format_drops_decimals = 0; + int looks_numeric = 0; if (!format) { @@ -815,12 +1036,12 @@ format = tls_serialization_float_format; else #endif - if (global_serialization_float_format) + if (global_serialization_float_format) format = global_serialization_float_format; else format = std_format; } - size = snprintf(buf, sizeof(buf), format, jso->o.c_double); + size = snprintf(buf, sizeof(buf), format, jsodbl->c_double); if (size < 0) return -1; @@ -834,11 +1055,13 @@ if (format == std_format || strstr(format, ".0f") == NULL) format_drops_decimals = 1; - if (size < (int)sizeof(buf) - 2 && - isdigit((int)buf[0]) && /* Looks like *some* kind of number */ - !p && /* Has no decimal point */ + looks_numeric = /* Looks like *some* kind of number */ + isdigit((unsigned char)buf[0]) || + (size > 1 && buf[0] == '-' && isdigit((unsigned char)buf[1])); + + if (size < (int)sizeof(buf) - 2 && looks_numeric && !p && /* Has no decimal point */ strchr(buf, 'e') == NULL && /* Not scientific notation */ - format_drops_decimals) + format_drops_decimals) { // Ensure it looks like a float, even if snprintf didn't, // unless a custom format is set to omit the decimal. @@ -849,12 +1072,15 @@ { /* last useful digit, always keep 1 zero */ p++; - for (q=p ; *q ; q++) { - if (*q!='0') p=q; + for (q = p; *q; q++) + { + if (*q != '0') + p = q; } /* drop trailing zeroes */ - *(++p) = 0; - size = p-buf; + if (*p != 0) + *(++p) = 0; + size = p - buf; } } // although unlikely, snprintf can fail @@ -869,35 +1095,30 @@ return size; } -static int json_object_double_to_json_string_default(struct json_object* jso, - struct printbuf *pb, - int level, - int flags) +static int json_object_double_to_json_string_default(struct json_object *jso, struct printbuf *pb, + int level, int flags) { - return json_object_double_to_json_string_format(jso, pb, level, flags, - NULL); + return json_object_double_to_json_string_format(jso, pb, level, flags, NULL); } -int json_object_double_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, - int flags) +int json_object_double_to_json_string(struct json_object *jso, struct printbuf *pb, int level, + int flags) { return json_object_double_to_json_string_format(jso, pb, level, flags, - (const char *)jso->_userdata); + (const char *)jso->_userdata); } -struct json_object* json_object_new_double(double d) +struct json_object *json_object_new_double(double d) { - struct json_object *jso = json_object_new(json_type_double); + struct json_object_double *jso = JSON_OBJECT_NEW(double); if (!jso) return NULL; - jso->_to_json_string = &json_object_double_to_json_string_default; - jso->o.c_double = d; - return jso; + jso->base._to_json_string = &json_object_double_to_json_string_default; + jso->c_double = d; + return &jso->base; } -struct json_object* json_object_new_double_s(double d, const char *ds) +struct json_object *json_object_new_double_s(double d, const char *ds) { char *new_ds; struct json_object *jso = json_object_new_double(d); @@ -911,13 +1132,24 @@ errno = ENOMEM; return NULL; } - json_object_set_serializer(jso, json_object_userdata_to_json_string, - new_ds, json_object_free_userdata); + json_object_set_serializer(jso, _json_object_userdata_to_json_string, new_ds, + json_object_free_userdata); return jso; } -int json_object_userdata_to_json_string(struct json_object *jso, - struct printbuf *pb, int level, int flags) +/* + * A wrapper around json_object_userdata_to_json_string() used only + * by json_object_new_double_s() just so json_object_set_double() can + * detect when it needs to reset the serializer to the default. + */ +static int _json_object_userdata_to_json_string(struct json_object *jso, struct printbuf *pb, + int level, int flags) +{ + return json_object_userdata_to_json_string(jso, pb, level, flags); +} + +int json_object_userdata_to_json_string(struct json_object *jso, struct printbuf *pb, int level, + int flags) { int userdata_len = strlen((const char *)jso->_userdata); printbuf_memappend(pb, (const char *)jso->_userdata, userdata_len); @@ -931,181 +1163,222 @@ double json_object_get_double(const struct json_object *jso) { - double cdouble; - char *errPtr = NULL; + double cdouble; + char *errPtr = NULL; + + if (!jso) + return 0.0; + switch (jso->o_type) + { + case json_type_double: return JC_DOUBLE_C(jso)->c_double; + case json_type_int: + switch (JC_INT_C(jso)->cint_type) + { + case json_object_int_type_int64: return JC_INT_C(jso)->cint.c_int64; + case json_object_int_type_uint64: return JC_INT_C(jso)->cint.c_uint64; + default: json_abort("invalid cint_type"); + } + case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; + case json_type_string: + errno = 0; + cdouble = strtod(get_string_component(jso), &errPtr); + + /* if conversion stopped at the first character, return 0.0 */ + if (errPtr == get_string_component(jso)) + { + errno = EINVAL; + return 0.0; + } + + /* + * Check that the conversion terminated on something sensible + * + * For example, { "pay" : 123AB } would parse as 123. + */ + if (*errPtr != '\0') + { + errno = EINVAL; + return 0.0; + } - if(!jso) return 0.0; - switch(jso->o_type) { - case json_type_double: - return jso->o.c_double; - case json_type_int: - return jso->o.c_int64; - case json_type_boolean: - return jso->o.c_boolean; - case json_type_string: - errno = 0; - cdouble = strtod(get_string_component(jso), &errPtr); - - /* if conversion stopped at the first character, return 0.0 */ - if (errPtr == get_string_component(jso)) - return 0.0; - - /* - * Check that the conversion terminated on something sensible - * - * For example, { "pay" : 123AB } would parse as 123. - */ - if (*errPtr != '\0') - return 0.0; - - /* - * If strtod encounters a string which would exceed the - * capacity of a double, it returns +/- HUGE_VAL and sets - * errno to ERANGE. But +/- HUGE_VAL is also a valid result - * from a conversion, so we need to check errno. - * - * Underflow also sets errno to ERANGE, but it returns 0 in - * that case, which is what we will return anyway. - * - * See CERT guideline ERR30-C - */ - if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) && - (ERANGE == errno)) - cdouble = 0.0; - return cdouble; - default: - return 0.0; - } + /* + * If strtod encounters a string which would exceed the + * capacity of a double, it returns +/- HUGE_VAL and sets + * errno to ERANGE. But +/- HUGE_VAL is also a valid result + * from a conversion, so we need to check errno. + * + * Underflow also sets errno to ERANGE, but it returns 0 in + * that case, which is what we will return anyway. + * + * See CERT guideline ERR30-C + */ + if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) && (ERANGE == errno)) + cdouble = 0.0; + return cdouble; + default: errno = EINVAL; return 0.0; + } } -int json_object_set_double(struct json_object *jso,double new_value){ - if (!jso || jso->o_type!=json_type_double) +int json_object_set_double(struct json_object *jso, double new_value) +{ + if (!jso || jso->o_type != json_type_double) return 0; - jso->o.c_double=new_value; + JC_DOUBLE(jso)->c_double = new_value; + if (jso->_to_json_string == &_json_object_userdata_to_json_string) + json_object_set_serializer(jso, NULL, NULL, NULL); return 1; } /* json_object_string */ -static int json_object_string_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, - int flags) +static int json_object_string_to_json_string(struct json_object *jso, struct printbuf *pb, + int level, int flags) { + ssize_t len = JC_STRING(jso)->len; printbuf_strappend(pb, "\""); - json_escape_str(pb, get_string_component(jso), jso->o.c_string.len, flags); + json_escape_str(pb, get_string_component(jso), len < 0 ? -(ssize_t)len : len, flags); printbuf_strappend(pb, "\""); return 0; } -static void json_object_string_delete(struct json_object* jso) +static void json_object_string_delete(struct json_object *jso) { - if(jso->o.c_string.len >= LEN_DIRECT_STRING_DATA) - free(jso->o.c_string.str.ptr); + if (JC_STRING(jso)->len < 0) + free(JC_STRING(jso)->c_string.pdata); json_object_generic_delete(jso); } -struct json_object* json_object_new_string(const char *s) +static struct json_object *_json_object_new_string(const char *s, const size_t len) { - struct json_object *jso = json_object_new(json_type_string); + size_t objsize; + struct json_object_string *jso; + + /* + * Structures Actual memory layout + * ------------------- -------------------- + * [json_object_string [json_object_string + * [json_object] [json_object] + * ...other fields... ...other fields... + * c_string] len + * bytes + * of + * string + * data + * \0] + */ + if (len > (SSIZE_T_MAX - (sizeof(*jso) - sizeof(jso->c_string)) - 1)) + return NULL; + objsize = (sizeof(*jso) - sizeof(jso->c_string)) + len + 1; + if (len < sizeof(void *)) + // We need a minimum size to support json_object_set_string() mutability + // so we can stuff a pointer into pdata :( + objsize += sizeof(void *) - len; + + jso = (struct json_object_string *)json_object_new(json_type_string, objsize, + &json_object_string_to_json_string); + if (!jso) return NULL; - jso->_delete = &json_object_string_delete; - jso->_to_json_string = &json_object_string_to_json_string; - jso->o.c_string.len = strlen(s); - if(jso->o.c_string.len < LEN_DIRECT_STRING_DATA) { - memcpy(jso->o.c_string.str.data, s, jso->o.c_string.len); - } else { - jso->o.c_string.str.ptr = strdup(s); - if (!jso->o.c_string.str.ptr) - { - json_object_generic_delete(jso); - errno = ENOMEM; - return NULL; - } - } - return jso; + jso->len = len; + memcpy(jso->c_string.idata, s, len); + jso->c_string.idata[len] = '\0'; + return &jso->base; } -struct json_object* json_object_new_string_len(const char *s, int len) +struct json_object *json_object_new_string(const char *s) { - char *dstbuf; - struct json_object *jso = json_object_new(json_type_string); - if (!jso) - return NULL; - jso->_delete = &json_object_string_delete; - jso->_to_json_string = &json_object_string_to_json_string; - if(len < LEN_DIRECT_STRING_DATA) { - dstbuf = jso->o.c_string.str.data; - } else { - jso->o.c_string.str.ptr = (char*)malloc(len + 1); - if (!jso->o.c_string.str.ptr) - { - json_object_generic_delete(jso); - errno = ENOMEM; - return NULL; - } - dstbuf = jso->o.c_string.str.ptr; - } - memcpy(dstbuf, (const void *)s, len); - dstbuf[len] = '\0'; - jso->o.c_string.len = len; - return jso; + return _json_object_new_string(s, strlen(s)); } -const char* json_object_get_string(struct json_object *jso) +struct json_object *json_object_new_string_len(const char *s, const int len) +{ + return _json_object_new_string(s, len); +} + +const char *json_object_get_string(struct json_object *jso) { if (!jso) return NULL; - switch(jso->o_type) + switch (jso->o_type) { - case json_type_string: - return get_string_component(jso); - default: - return json_object_to_json_string(jso); + case json_type_string: return get_string_component(jso); + default: return json_object_to_json_string(jso); } } - int json_object_get_string_len(const struct json_object *jso) { + ssize_t len; if (!jso) return 0; - switch(jso->o_type) + switch (jso->o_type) { case json_type_string: - return jso->o.c_string.len; - default: - return 0; + { + len = JC_STRING_C(jso)->len; + return (len < 0) ? -(ssize_t)len : len; + } + default: return 0; } } -int json_object_set_string(json_object* jso, const char* s) { - return json_object_set_string_len(jso, s, (int)(strlen(s))); -} +static int _json_object_set_string_len(json_object *jso, const char *s, size_t len) +{ + char *dstbuf; + ssize_t curlen; + ssize_t newlen; + if (jso == NULL || jso->o_type != json_type_string) + return 0; -int json_object_set_string_len(json_object* jso, const char* s, int len){ - char *dstbuf; - if (jso==NULL || jso->o_type!=json_type_string) return 0; - if (leno.c_string.str.data; - if (jso->o.c_string.len>=LEN_DIRECT_STRING_DATA) free(jso->o.c_string.str.ptr); - } else { - dstbuf=(char *)malloc(len+1); - if (dstbuf==NULL) return 0; - if (jso->o.c_string.len>=LEN_DIRECT_STRING_DATA) free(jso->o.c_string.str.ptr); - jso->o.c_string.str.ptr=dstbuf; + if (len >= SSIZE_T_MAX - 1) + // jso->len is a signed ssize_t, so it can't hold the + // full size_t range. + return 0; + + dstbuf = get_string_component_mutable(jso); + curlen = JC_STRING(jso)->len; + if (curlen < 0) + curlen = -curlen; + newlen = len; + + if ((ssize_t)len > curlen) + { + // We have no way to return the new ptr from realloc(jso, newlen) + // and we have no way of knowing whether there's extra room available + // so we need to stuff a pointer in to pdata :( + dstbuf = (char *)malloc(len + 1); + if (dstbuf == NULL) + return 0; + if (JC_STRING(jso)->len < 0) + free(JC_STRING(jso)->c_string.pdata); + JC_STRING(jso)->c_string.pdata = dstbuf; + newlen = -(ssize_t)len; + } + else if (JC_STRING(jso)->len < 0) + { + // We've got enough room in the separate allocated buffer, + // so use it as-is and continue to indicate that pdata is used. + newlen = -(ssize_t)len; } - jso->o.c_string.len=len; + memcpy(dstbuf, (const void *)s, len); dstbuf[len] = '\0'; - return 1; + JC_STRING(jso)->len = newlen; + return 1; +} + +int json_object_set_string(json_object *jso, const char *s) +{ + return _json_object_set_string_len(jso, s, strlen(s)); +} + +int json_object_set_string_len(json_object *jso, const char *s, int len) +{ + return _json_object_set_string_len(jso, s, len); } /* json_object_array */ -static int json_object_array_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, +static int json_object_array_to_json_string(struct json_object *jso, struct printbuf *pb, int level, int flags) { int had_children = 0; @@ -1114,7 +1387,7 @@ printbuf_strappend(pb, "["); if (flags & JSON_C_TO_STRING_PRETTY) printbuf_strappend(pb, "\n"); - for(ii=0; ii < json_object_array_length(jso); ii++) + for (ii = 0; ii < json_object_array_length(jso); ii++) { struct json_object *val; if (had_children) @@ -1124,85 +1397,82 @@ printbuf_strappend(pb, "\n"); } had_children = 1; - if (flags & JSON_C_TO_STRING_SPACED) + if (flags & JSON_C_TO_STRING_SPACED && !(flags & JSON_C_TO_STRING_PRETTY)) printbuf_strappend(pb, " "); indent(pb, level + 1, flags); val = json_object_array_get_idx(jso, ii); - if(val == NULL) + if (val == NULL) printbuf_strappend(pb, "null"); - else - if (val->_to_json_string(val, pb, level+1, flags) < 0) - return -1; + else if (val->_to_json_string(val, pb, level + 1, flags) < 0) + return -1; } if (flags & JSON_C_TO_STRING_PRETTY) { if (had_children) printbuf_strappend(pb, "\n"); - indent(pb,level,flags); + indent(pb, level, flags); } - if (flags & JSON_C_TO_STRING_SPACED) + if (flags & JSON_C_TO_STRING_SPACED && !(flags & JSON_C_TO_STRING_PRETTY)) return printbuf_strappend(pb, " ]"); return printbuf_strappend(pb, "]"); } static void json_object_array_entry_free(void *data) { - json_object_put((struct json_object*)data); + json_object_put((struct json_object *)data); } -static void json_object_array_delete(struct json_object* jso) +static void json_object_array_delete(struct json_object *jso) { - array_list_free(jso->o.c_array); + array_list_free(JC_ARRAY(jso)->c_array); json_object_generic_delete(jso); } -struct json_object* json_object_new_array(void) +struct json_object *json_object_new_array(void) { - struct json_object *jso = json_object_new(json_type_array); + return json_object_new_array_ext(ARRAY_LIST_DEFAULT_SIZE); +} +struct json_object *json_object_new_array_ext(int initial_size) +{ + struct json_object_array *jso = JSON_OBJECT_NEW(array); if (!jso) return NULL; - jso->_delete = &json_object_array_delete; - jso->_to_json_string = &json_object_array_to_json_string; - jso->o.c_array = array_list_new(&json_object_array_entry_free); - if(jso->o.c_array == NULL) + jso->c_array = array_list_new2(&json_object_array_entry_free, initial_size); + if (jso->c_array == NULL) { - free(jso); - return NULL; + free(jso); + return NULL; } - return jso; + return &jso->base; } -struct array_list* json_object_get_array(const struct json_object *jso) +struct array_list *json_object_get_array(const struct json_object *jso) { if (!jso) return NULL; - switch(jso->o_type) + switch (jso->o_type) { - case json_type_array: - return jso->o.c_array; - default: - return NULL; + case json_type_array: return JC_ARRAY_C(jso)->c_array; + default: return NULL; } } -void json_object_array_sort(struct json_object *jso, - int(*sort_fn)(const void *, const void *)) +void json_object_array_sort(struct json_object *jso, int (*sort_fn)(const void *, const void *)) { assert(json_object_get_type(jso) == json_type_array); - array_list_sort(jso->o.c_array, sort_fn); + array_list_sort(JC_ARRAY(jso)->c_array, sort_fn); } -struct json_object* json_object_array_bsearch( - const struct json_object *key, - const struct json_object *jso, - int (*sort_fn)(const void *, const void *)) +struct json_object *json_object_array_bsearch(const struct json_object *key, + const struct json_object *jso, + int (*sort_fn)(const void *, const void *)) { struct json_object **result; assert(json_object_get_type(jso) == json_type_array); - result = (struct json_object **)array_list_bsearch( - (const void **)(void *)&key, jso->o.c_array, sort_fn); + result = (struct json_object **)array_list_bsearch((const void **)(void *)&key, + JC_ARRAY_C(jso)->c_array, sort_fn); if (!result) return NULL; @@ -1212,37 +1482,34 @@ size_t json_object_array_length(const struct json_object *jso) { assert(json_object_get_type(jso) == json_type_array); - return array_list_length(jso->o.c_array); + return array_list_length(JC_ARRAY_C(jso)->c_array); } -int json_object_array_add(struct json_object *jso,struct json_object *val) +int json_object_array_add(struct json_object *jso, struct json_object *val) { assert(json_object_get_type(jso) == json_type_array); - return array_list_add(jso->o.c_array, val); + return array_list_add(JC_ARRAY(jso)->c_array, val); } -int json_object_array_put_idx(struct json_object *jso, size_t idx, - struct json_object *val) +int json_object_array_put_idx(struct json_object *jso, size_t idx, struct json_object *val) { assert(json_object_get_type(jso) == json_type_array); - return array_list_put_idx(jso->o.c_array, idx, val); + return array_list_put_idx(JC_ARRAY(jso)->c_array, idx, val); } int json_object_array_del_idx(struct json_object *jso, size_t idx, size_t count) { assert(json_object_get_type(jso) == json_type_array); - return array_list_del_idx(jso->o.c_array, idx, count); + return array_list_del_idx(JC_ARRAY(jso)->c_array, idx, count); } -struct json_object* json_object_array_get_idx(const struct json_object *jso, - size_t idx) +struct json_object *json_object_array_get_idx(const struct json_object *jso, size_t idx) { assert(json_object_get_type(jso) == json_type_array); - return (struct json_object*)array_list_get_idx(jso->o.c_array, idx); + return (struct json_object *)array_list_get_idx(JC_ARRAY_C(jso)->c_array, idx); } -static int json_array_equal(struct json_object* jso1, - struct json_object* jso2) +static int json_array_equal(struct json_object *jso1, struct json_object *jso2) { size_t len, i; @@ -1250,16 +1517,28 @@ if (len != json_object_array_length(jso2)) return 0; - for (i = 0; i < len; i++) { + for (i = 0; i < len; i++) + { if (!json_object_equal(json_object_array_get_idx(jso1, i), - json_object_array_get_idx(jso2, i))) + json_object_array_get_idx(jso2, i))) return 0; } return 1; } -static int json_object_all_values_equal(struct json_object* jso1, - struct json_object* jso2) +int json_object_array_shrink(struct json_object *jso, int empty_slots) +{ + if (empty_slots < 0) + json_abort("json_object_array_shrink called with negative empty_slots"); + return array_list_shrink(JC_ARRAY(jso)->c_array, empty_slots); +} + +struct json_object *json_object_new_null(void) +{ + return NULL; +} + +static int json_object_all_values_equal(struct json_object *jso1, struct json_object *jso2) { struct json_object_iter iter; struct json_object *sub; @@ -1267,25 +1546,27 @@ assert(json_object_get_type(jso1) == json_type_object); assert(json_object_get_type(jso2) == json_type_object); /* Iterate over jso1 keys and see if they exist and are equal in jso2 */ - json_object_object_foreachC(jso1, iter) { - if (!lh_table_lookup_ex(jso2->o.c_object, (void*)iter.key, - (void**)(void *)&sub)) + json_object_object_foreachC(jso1, iter) + { + if (!lh_table_lookup_ex(JC_OBJECT(jso2)->c_object, (void *)iter.key, + (void **)(void *)&sub)) return 0; if (!json_object_equal(iter.val, sub)) return 0; - } + } /* Iterate over jso2 keys to see if any exist that are not in jso1 */ - json_object_object_foreachC(jso2, iter) { - if (!lh_table_lookup_ex(jso1->o.c_object, (void*)iter.key, - (void**)(void *)&sub)) + json_object_object_foreachC(jso2, iter) + { + if (!lh_table_lookup_ex(JC_OBJECT(jso1)->c_object, (void *)iter.key, + (void **)(void *)&sub)) return 0; - } + } return 1; } -int json_object_equal(struct json_object* jso1, struct json_object* jso2) +int json_object_equal(struct json_object *jso1, struct json_object *jso2) { if (jso1 == jso2) return 1; @@ -1296,30 +1577,44 @@ if (jso1->o_type != jso2->o_type) return 0; - switch(jso1->o_type) { - case json_type_boolean: - return (jso1->o.c_boolean == jso2->o.c_boolean); + switch (jso1->o_type) + { + case json_type_boolean: return (JC_BOOL(jso1)->c_boolean == JC_BOOL(jso2)->c_boolean); - case json_type_double: - return (jso1->o.c_double == jso2->o.c_double); + case json_type_double: return (JC_DOUBLE(jso1)->c_double == JC_DOUBLE(jso2)->c_double); - case json_type_int: - return (jso1->o.c_int64 == jso2->o.c_int64); + case json_type_int: + { + struct json_object_int *int1 = JC_INT(jso1); + struct json_object_int *int2 = JC_INT(jso2); + if (int1->cint_type == json_object_int_type_int64) + { + if (int2->cint_type == json_object_int_type_int64) + return (int1->cint.c_int64 == int2->cint.c_int64); + if (int1->cint.c_int64 < 0) + return 0; + return ((uint64_t)int1->cint.c_int64 == int2->cint.c_uint64); + } + // else jso1 is a uint64 + if (int2->cint_type == json_object_int_type_uint64) + return (int1->cint.c_uint64 == int2->cint.c_uint64); + if (int2->cint.c_int64 < 0) + return 0; + return (int1->cint.c_uint64 == (uint64_t)int2->cint.c_int64); + } - case json_type_string: - return (jso1->o.c_string.len == jso2->o.c_string.len && - memcmp(get_string_component(jso1), - get_string_component(jso2), - jso1->o.c_string.len) == 0); + case json_type_string: + { + return (json_object_get_string_len(jso1) == json_object_get_string_len(jso2) && + memcmp(get_string_component(jso1), get_string_component(jso2), + json_object_get_string_len(jso1)) == 0); + } - case json_type_object: - return json_object_all_values_equal(jso1, jso2); + case json_type_object: return json_object_all_values_equal(jso1, jso2); - case json_type_array: - return json_array_equal(jso1, jso2); + case json_type_array: return json_array_equal(jso1, jso2); - case json_type_null: - return 1; + case json_type_null: return 1; }; return 0; @@ -1330,21 +1625,23 @@ if (!src->_userdata && !src->_user_delete) return 0; - if (dst->_to_json_string == json_object_userdata_to_json_string) + if (dst->_to_json_string == json_object_userdata_to_json_string || + dst->_to_json_string == _json_object_userdata_to_json_string) { dst->_userdata = strdup(src->_userdata); } // else if ... other supported serializers ... else { - _json_c_set_last_err("json_object_deep_copy: unable to copy unknown serializer data: %p\n", dst->_to_json_string); + _json_c_set_last_err( + "json_object_deep_copy: unable to copy unknown serializer data: %p\n", + (void *)dst->_to_json_string); return -1; } dst->_user_delete = src->_user_delete; return 0; } - /** * The default shallow copy implementation. Simply creates a new object of the same * type but does *not* copy over _userdata nor retain any custom serializer. @@ -1353,39 +1650,39 @@ * * This always returns -1 or 1. It will never return 2 since it does not copy the serializer. */ -int json_c_shallow_copy_default(json_object *src, json_object *parent, const char *key, size_t index, json_object **dst) +int json_c_shallow_copy_default(json_object *src, json_object *parent, const char *key, + size_t index, json_object **dst) { - switch (src->o_type) { - case json_type_boolean: - *dst = json_object_new_boolean(src->o.c_boolean); - break; + switch (src->o_type) + { + case json_type_boolean: *dst = json_object_new_boolean(JC_BOOL(src)->c_boolean); break; - case json_type_double: - *dst = json_object_new_double(src->o.c_double); - break; + case json_type_double: *dst = json_object_new_double(JC_DOUBLE(src)->c_double); break; case json_type_int: - *dst = json_object_new_int64(src->o.c_int64); + switch (JC_INT(src)->cint_type) + { + case json_object_int_type_int64: + *dst = json_object_new_int64(JC_INT(src)->cint.c_int64); + break; + case json_object_int_type_uint64: + *dst = json_object_new_uint64(JC_INT(src)->cint.c_uint64); + break; + default: json_abort("invalid cint_type"); + } break; - case json_type_string: - *dst = json_object_new_string(get_string_component(src)); - break; + case json_type_string: *dst = json_object_new_string(get_string_component(src)); break; - case json_type_object: - *dst = json_object_new_object(); - break; + case json_type_object: *dst = json_object_new_object(); break; - case json_type_array: - *dst = json_object_new_array(); - break; + case json_type_array: *dst = json_object_new_array(); break; - default: - errno = EINVAL; - return -1; + default: errno = EINVAL; return -1; } - if (!*dst) { + if (!*dst) + { errno = ENOMEM; return -1; } @@ -1400,7 +1697,10 @@ * * Note: caller is responsible for freeing *dst if this fails and returns -1. */ -static int json_object_deep_copy_recursive(struct json_object *src, struct json_object *parent, const char *key_in_parent, size_t index_in_parent, struct json_object **dst, json_c_shallow_copy_fn *shallow_copy) +static int json_object_deep_copy_recursive(struct json_object *src, struct json_object *parent, + const char *key_in_parent, size_t index_in_parent, + struct json_object **dst, + json_c_shallow_copy_fn *shallow_copy) { struct json_object_iter iter; size_t src_array_len, ii; @@ -1415,14 +1715,17 @@ } assert(*dst != NULL); - switch (src->o_type) { + switch (src->o_type) + { case json_type_object: - json_object_object_foreachC(src, iter) { + json_object_object_foreachC(src, iter) + { struct json_object *jso = NULL; /* This handles the `json_type_null` case */ if (!iter.val) jso = NULL; - else if (json_object_deep_copy_recursive(iter.val, src, iter.key, -1, &jso, shallow_copy) < 0) + else if (json_object_deep_copy_recursive(iter.val, src, iter.key, -1, &jso, + shallow_copy) < 0) { json_object_put(jso); return -1; @@ -1438,13 +1741,15 @@ case json_type_array: src_array_len = json_object_array_length(src); - for (ii = 0; ii < src_array_len; ii++) { + for (ii = 0; ii < src_array_len; ii++) + { struct json_object *jso = NULL; struct json_object *jso1 = json_object_array_get_idx(src, ii); /* This handles the `json_type_null` case */ if (!jso1) jso = NULL; - else if (json_object_deep_copy_recursive(jso1, src, NULL, ii, &jso, shallow_copy) < 0) + else if (json_object_deep_copy_recursive(jso1, src, NULL, ii, &jso, + shallow_copy) < 0) { json_object_put(jso); return -1; @@ -1469,12 +1774,14 @@ return 0; } -int json_object_deep_copy(struct json_object *src, struct json_object **dst, json_c_shallow_copy_fn *shallow_copy) +int json_object_deep_copy(struct json_object *src, struct json_object **dst, + json_c_shallow_copy_fn *shallow_copy) { int rc; /* Check if arguments are sane ; *dst must not point to a non-NULL object */ - if (!src || !dst || *dst) { + if (!src || !dst || *dst) + { errno = EINVAL; return -1; } @@ -1483,7 +1790,8 @@ shallow_copy = json_c_shallow_copy_default; rc = json_object_deep_copy_recursive(src, NULL, NULL, -1, dst, shallow_copy); - if (rc < 0) { + if (rc < 0) + { json_object_put(*dst); *dst = NULL; } @@ -1491,3 +1799,9 @@ return rc; } +static void json_abort(const char *message) +{ + if (message != NULL) + fprintf(stderr, "json-c aborts with error: %s\n", message); + abort(); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_object.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_object.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_object.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_object.h 2022-04-15 07:49:21.000000000 +0000 @@ -18,31 +18,17 @@ #define _json_object_h_ #ifdef __GNUC__ -#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated)) -#elif defined(_MSC_VER) -#define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func -#elif defined(__clang__) -#define THIS_FUNCTION_IS_DEPRECATED(func) func __deprecated -#else -#define THIS_FUNCTION_IS_DEPRECATED(func) func -#endif - -#ifdef __GNUC__ #define JSON_C_CONST_FUNCTION(func) func __attribute__((const)) #else #define JSON_C_CONST_FUNCTION(func) func #endif -#if defined(_MSC_VER) -#define JSON_EXPORT __declspec(dllexport) -#else -#define JSON_EXPORT extern -#endif - -#include #include "json_inttypes.h" +#include "json_types.h" #include "printbuf.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -54,13 +40,13 @@ * json_object_to_file_ext() functions which causes the output * to have no extra whitespace or formatting applied. */ -#define JSON_C_TO_STRING_PLAIN 0 +#define JSON_C_TO_STRING_PLAIN 0 /** * A flag for the json_object_to_json_string_ext() and * json_object_to_file_ext() functions which causes the output to have * minimal whitespace inserted to make things slightly more readable. */ -#define JSON_C_TO_STRING_SPACED (1<<0) +#define JSON_C_TO_STRING_SPACED (1 << 0) /** * A flag for the json_object_to_json_string_ext() and * json_object_to_file_ext() functions which causes @@ -69,7 +55,7 @@ * See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/ * for an example of the format. */ -#define JSON_C_TO_STRING_PRETTY (1<<1) +#define JSON_C_TO_STRING_PRETTY (1 << 1) /** * A flag for the json_object_to_json_string_ext() and * json_object_to_file_ext() functions which causes @@ -77,28 +63,28 @@ * * Instead of a "Two Space Tab" this gives a single tab character. */ -#define JSON_C_TO_STRING_PRETTY_TAB (1<<3) +#define JSON_C_TO_STRING_PRETTY_TAB (1 << 3) /** * A flag to drop trailing zero for float values */ -#define JSON_C_TO_STRING_NOZERO (1<<2) +#define JSON_C_TO_STRING_NOZERO (1 << 2) /** * Don't escape forward slashes. */ -#define JSON_C_TO_STRING_NOSLASHESCAPE (1<<4) +#define JSON_C_TO_STRING_NOSLASHESCAPE (1 << 4) /** * A flag for the json_object_object_add_ex function which * causes the value to be added without a check if it already exists. - * Note: it is the responsibilty of the caller to ensure that no + * Note: it is the responsibility of the caller to ensure that no * key is added multiple times. If this is done, results are * unpredictable. While this option is somewhat dangerous, it * permits potentially large performance savings in code that * knows for sure the key values are unique (e.g. because the * code adds a well-known set of constant key values). */ -#define JSON_C_OBJECT_ADD_KEY_IS_NEW (1<<1) +#define JSON_C_OBJECT_ADD_KEY_IS_NEW (1 << 1) /** * A flag for the json_object_object_add_ex function which * flags the key as being constant memory. This means that @@ -116,13 +102,7 @@ * json_object_object_add_ex(obj, "ip", json, * JSON_C_OBJECT_KEY_IS_CONSTANT); */ -#define JSON_C_OBJECT_KEY_IS_CONSTANT (1<<2) - -#undef FALSE -#define FALSE ((json_bool)0) - -#undef TRUE -#define TRUE ((json_bool)1) +#define JSON_C_OBJECT_KEY_IS_CONSTANT (1 << 2) /** * Set the global value of an option, which will apply to all @@ -140,68 +120,46 @@ */ #define JSON_C_OPTION_THREAD (1) -/** - * A structure to use with json_object_object_foreachC() loops. - * Contains key, val and entry members. - */ -struct json_object_iter -{ - char *key; - struct json_object *val; - struct lh_entry *entry; -}; -typedef struct json_object_iter json_object_iter; - -typedef int json_bool; - -/** - * @brief The core type for all type of JSON objects handled by json-c - */ -typedef struct json_object json_object; - -/** - * Type of custom user delete functions. See json_object_set_serializer. - */ -typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata); - -/** - * Type of a custom serialization function. See json_object_set_serializer. - */ -typedef int (json_object_to_json_string_fn)(struct json_object *jso, - struct printbuf *pb, - int level, - int flags); - -/* supported object types */ - -typedef enum json_type { - /* If you change this, be sure to update json_type_to_name() too */ - json_type_null, - json_type_boolean, - json_type_double, - json_type_int, - json_type_object, - json_type_array, - json_type_string -} json_type; - /* reference counting functions */ /** - * Increment the reference count of json_object, thereby grabbing shared - * ownership of obj. + * Increment the reference count of json_object, thereby taking ownership of it. * - * @param obj the json_object instance + * Cases where you might need to increase the refcount include: + * - Using an object field or array index (retrieved through + * `json_object_object_get()` or `json_object_array_get_idx()`) + * beyond the lifetime of the parent object. + * - Detaching an object field or array index from its parent object + * (using `json_object_object_del()` or `json_object_array_del_idx()`) + * - Sharing a json_object with multiple (not necesarily parallel) threads + * of execution that all expect to free it (with `json_object_put()`) when + * they're done. + * + * @param obj the json_object instance + * @see json_object_put() + * @see json_object_object_get() + * @see json_object_array_get_idx() */ -JSON_EXPORT struct json_object* json_object_get(struct json_object *obj); +JSON_EXPORT struct json_object *json_object_get(struct json_object *obj); /** * Decrement the reference count of json_object and free if it reaches zero. + * * You must have ownership of obj prior to doing this or you will cause an - * imbalance in the reference count. + * imbalance in the reference count, leading to a classic use-after-free bug. + * In particular, you normally do not need to call `json_object_put()` on the + * json_object returned by `json_object_object_get()` or `json_object_array_get_idx()`. + * + * Just like after calling `free()` on a block of memory, you must not use + * `obj` after calling `json_object_put()` on it or any object that it + * is a member of (unless you know you've called `json_object_get(obj)` to + * explicitly increment the refcount). + * + * NULL may be passed, which which case this is a no-op. * * @param obj the json_object instance * @returns 1 if the object was freed. + * @see json_object_get() */ JSON_EXPORT int json_object_put(struct json_object *obj); @@ -235,7 +193,6 @@ */ JSON_EXPORT enum json_type json_object_get_type(const struct json_object *obj); - /** Stringify object to json format. * Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED) * The pointer you get is an internal of your json object. You don't @@ -245,7 +202,7 @@ * @param obj the json_object instance * @returns a string in JSON format */ -JSON_EXPORT const char* json_object_to_json_string(struct json_object *obj); +JSON_EXPORT const char *json_object_to_json_string(struct json_object *obj); /** Stringify object to json format * @see json_object_to_json_string() for details on how to free string. @@ -253,8 +210,7 @@ * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants * @returns a string in JSON format */ -JSON_EXPORT const char* json_object_to_json_string_ext(struct json_object *obj, int -flags); +JSON_EXPORT const char *json_object_to_json_string_ext(struct json_object *obj, int flags); /** Stringify object to json format * @see json_object_to_json_string() for details on how to free string. @@ -263,8 +219,8 @@ * @param length a pointer where, if not NULL, the length (without null) is stored * @returns a string in JSON format and the length if not NULL */ -JSON_EXPORT const char* json_object_to_json_string_length(struct json_object *obj, int -flags, size_t *length); +JSON_EXPORT const char *json_object_to_json_string_length(struct json_object *obj, int flags, + size_t *length); /** * Returns the userdata set by json_object_set_userdata() or @@ -272,7 +228,7 @@ * * @param jso the object to return the userdata for */ -JSON_EXPORT void* json_object_get_userdata(json_object *jso); +JSON_EXPORT void *json_object_get_userdata(json_object *jso); /** * Set an opaque userdata value for an object @@ -300,7 +256,7 @@ * @param user_delete an optional function from freeing userdata */ JSON_EXPORT void json_object_set_userdata(json_object *jso, void *userdata, - json_object_delete_fn *user_delete); + json_object_delete_fn *user_delete); /** * Set a custom serialization function to be used when this particular object @@ -333,9 +289,8 @@ * @param user_delete an optional function from freeing userdata */ JSON_EXPORT void json_object_set_serializer(json_object *jso, - json_object_to_json_string_fn *to_string_func, - void *userdata, - json_object_delete_fn *user_delete); + json_object_to_json_string_fn *to_string_func, + void *userdata, json_object_delete_fn *user_delete); #ifdef __clang__ /* @@ -354,7 +309,7 @@ * @param jso unused * @param userdata the pointer that is passed to free(). */ -json_object_delete_fn json_object_free_userdata; +JSON_EXPORT json_object_delete_fn json_object_free_userdata; /** * Copy the jso->_userdata string over to pb as-is. @@ -365,14 +320,13 @@ * @param level Ignored. * @param flags Ignored. */ -json_object_to_json_string_fn json_object_userdata_to_json_string; +JSON_EXPORT json_object_to_json_string_fn json_object_userdata_to_json_string; #ifdef __clang__ /* } */ #pragma clang diagnostic pop #endif - /* object type methods */ /** Create a new empty object with a reference count of 1. The caller of @@ -385,18 +339,18 @@ * * @returns a json_object of type json_type_object */ -JSON_EXPORT struct json_object* json_object_new_object(void); +JSON_EXPORT struct json_object *json_object_new_object(void); /** Get the hashtable of a json_object of type json_type_object * @param obj the json_object instance * @returns a linkhash */ -JSON_EXPORT struct lh_table* json_object_get_object(const struct json_object *obj); +JSON_EXPORT struct lh_table *json_object_get_object(const struct json_object *obj); /** Get the size of an object in terms of the number of fields it has. * @param obj the json_object whose length to return */ -JSON_EXPORT int json_object_object_length(const struct json_object* obj); +JSON_EXPORT int json_object_object_length(const struct json_object *obj); /** Get the sizeof (struct json_object). * @returns a size_t with the sizeof (struct json_object) @@ -405,15 +359,21 @@ /** Add an object field to a json_object of type json_type_object * - * The reference count will *not* be incremented. This is to make adding - * fields to objects in code more compact. If you want to retain a reference - * to an added object, independent of the lifetime of obj, you must wrap the - * passed object with json_object_get. + * The reference count of `val` will *not* be incremented, in effect + * transferring ownership that object to `obj`, and thus `val` will be + * freed when `obj` is. (i.e. through `json_object_put(obj)`) + * + * If you want to retain a reference to the added object, independent + * of the lifetime of obj, you must increment the refcount with + * `json_object_get(val)` (and later release it with json_object_put()). + * + * Since ownership transfers to `obj`, you must make sure + * that you do in fact have ownership over `val`. For instance, + * json_object_new_object() will give you ownership until you transfer it, + * whereas json_object_object_get() does not. * - * Upon calling this, the ownership of val transfers to obj. Thus you must - * make sure that you do in fact have ownership over this object. For instance, - * json_object_new_object will give you ownership until you transfer it, - * whereas json_object_object_get does not. + * Any previous object stored under `key` in `obj` will have its refcount + * decremented, and be freed normally if that drops to zero. * * @param obj the json_object instance * @param key the object field name (a private copy will be duplicated) @@ -422,8 +382,8 @@ * @return On success, 0 is returned. * On error, a negative value is returned. */ -JSON_EXPORT int json_object_object_add(struct json_object* obj, const char *key, - struct json_object *val); +JSON_EXPORT int json_object_object_add(struct json_object *obj, const char *key, + struct json_object *val); /** Add an object field to a json_object of type json_type_object * @@ -435,20 +395,18 @@ * @param obj the json_object instance * @param key the object field name (a private copy will be duplicated) * @param val a json_object or NULL member to associate with the given field - * @param opts process-modifying options. To specify multiple options, use - * arithmetic or (OPT1|OPT2) + * @param opts process-modifying options. To specify multiple options, use + * (OPT1|OPT2) */ -JSON_EXPORT int json_object_object_add_ex(struct json_object* obj, - const char *const key, - struct json_object *const val, - const unsigned opts); +JSON_EXPORT int json_object_object_add_ex(struct json_object *obj, const char *const key, + struct json_object *const val, const unsigned opts); /** Get the json_object associate with a given object field. * Deprecated/discouraged: used json_object_object_get_ex instead. * * This returns NULL if the field is found but its value is null, or if * the field is not found, or if obj is not a json_type_object. If you - * need to distinguis between these cases, use json_object_object_get_ex(). + * need to distinguish between these cases, use json_object_object_get_ex(). * * *No* reference counts will be changed. There is no need to manually adjust * reference counts through the json_object_put/json_object_get methods unless @@ -464,8 +422,8 @@ * @param key the object field name * @returns the json_object associated with the given field name */ -JSON_EXPORT struct json_object* json_object_object_get(const struct json_object* obj, - const char *key); +JSON_EXPORT struct json_object *json_object_object_get(const struct json_object *obj, + const char *key); /** Get the json_object associated with a given object field. * @@ -485,9 +443,8 @@ * It is safe to pass a NULL value. * @returns whether or not the key exists */ -JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object* obj, - const char *key, - struct json_object **value); +JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object *obj, const char *key, + struct json_object **value); /** Delete the given json_object field * @@ -498,7 +455,7 @@ * @param obj the json_object instance * @param key the object field name */ -JSON_EXPORT void json_object_object_del(struct json_object* obj, const char *key); +JSON_EXPORT void json_object_object_del(struct json_object *obj, const char *key); /** * Iterate through all keys and values of an object. @@ -515,31 +472,35 @@ */ #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L -# define json_object_object_foreach(obj,key,val) \ - char *key = NULL; \ - struct json_object *val __attribute__((__unused__)) = NULL; \ - for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \ - ({ if(entry ## key) { \ - key = (char*)lh_entry_k(entry ## key); \ - val = (struct json_object*)lh_entry_v(entry ## key); \ - entry_next ## key = entry ## key->next; \ - } ; entry ## key; }); \ - entry ## key = entry_next ## key ) +#define json_object_object_foreach(obj, key, val) \ + char *key = NULL; \ + struct json_object *val __attribute__((__unused__)) = NULL; \ + for (struct lh_entry *entry##key = json_object_get_object(obj)->head, \ + *entry_next##key = NULL; \ + ({ \ + if (entry##key) \ + { \ + key = (char *)lh_entry_k(entry##key); \ + val = (struct json_object *)lh_entry_v(entry##key); \ + entry_next##key = entry##key->next; \ + }; \ + entry##key; \ + }); \ + entry##key = entry_next##key) #else /* ANSI C or MSC */ -# define json_object_object_foreach(obj,key,val) \ - char *key = NULL;\ - struct json_object *val = NULL; \ - struct lh_entry *entry ## key; \ - struct lh_entry *entry_next ## key = NULL; \ - for(entry ## key = json_object_get_object(obj)->head; \ - (entry ## key ? ( \ - key = (char*)lh_entry_k(entry ## key), \ - val = (struct json_object*)lh_entry_v(entry ## key), \ - entry_next ## key = entry ## key->next, \ - entry ## key) : 0); \ - entry ## key = entry_next ## key) +#define json_object_object_foreach(obj, key, val) \ + char *key = NULL; \ + struct json_object *val = NULL; \ + struct lh_entry *entry##key; \ + struct lh_entry *entry_next##key = NULL; \ + for (entry##key = json_object_get_object(obj)->head; \ + (entry##key ? (key = (char *)lh_entry_k(entry##key), \ + val = (struct json_object *)lh_entry_v(entry##key), \ + entry_next##key = entry##key->next, entry##key) \ + : 0); \ + entry##key = entry_next##key) #endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */ @@ -547,23 +508,38 @@ * @param obj the json_object instance * @param iter the object iterator, use type json_object_iter */ -#define json_object_object_foreachC(obj,iter) \ - for(iter.entry = json_object_get_object(obj)->head; \ - (iter.entry ? (iter.key = (char*)lh_entry_k(iter.entry), iter.val = (struct json_object*)lh_entry_v(iter.entry), iter.entry) : 0); \ - iter.entry = iter.entry->next) +#define json_object_object_foreachC(obj, iter) \ + for (iter.entry = json_object_get_object(obj)->head; \ + (iter.entry ? (iter.key = (char *)lh_entry_k(iter.entry), \ + iter.val = (struct json_object *)lh_entry_v(iter.entry), iter.entry) \ + : 0); \ + iter.entry = iter.entry->next) /* Array type methods */ /** Create a new empty json_object of type json_type_array + * with 32 slots allocated. + * If you know the array size you'll need ahead of time, use + * json_object_new_array_ext() instead. + * @see json_object_new_array_ext() + * @see json_object_array_shrink() + * @returns a json_object of type json_type_array + */ +JSON_EXPORT struct json_object *json_object_new_array(void); + +/** Create a new empty json_object of type json_type_array + * with the desired number of slots allocated. + * @see json_object_array_shrink() + * @param initial_size the number of slots to allocate * @returns a json_object of type json_type_array */ -JSON_EXPORT struct json_object* json_object_new_array(void); +JSON_EXPORT struct json_object *json_object_new_array_ext(int initial_size); /** Get the arraylist of a json_object of type json_type_array * @param obj the json_object instance * @returns an arraylist */ -JSON_EXPORT struct array_list* json_object_get_array(const struct json_object *obj); +JSON_EXPORT struct array_list *json_object_get_array(const struct json_object *obj); /** Get the length of a json_object of type json_type_array * @param obj the json_object instance @@ -579,7 +555,8 @@ * @param jso the json_object instance * @param sort_fn a sorting function */ -JSON_EXPORT void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)); +JSON_EXPORT void json_object_array_sort(struct json_object *jso, + int (*sort_fn)(const void *, const void *)); /** Binary search a sorted array for a specified key object. * @@ -595,10 +572,9 @@ * * @return the wanted json_object instance */ -JSON_EXPORT struct json_object* json_object_array_bsearch( - const struct json_object *key, - const struct json_object *jso, - int (*sort_fn)(const void *, const void *)); +JSON_EXPORT struct json_object * +json_object_array_bsearch(const struct json_object *key, const struct json_object *jso, + int (*sort_fn)(const void *, const void *)); /** Add an element to the end of a json_object of type json_type_array * @@ -609,8 +585,7 @@ * @param obj the json_object instance * @param val the json_object to be added */ -JSON_EXPORT int json_object_array_add(struct json_object *obj, - struct json_object *val); +JSON_EXPORT int json_object_array_add(struct json_object *obj, struct json_object *val); /** Insert or replace an element at a specified index in an array (a json_object of type json_type_array) * @@ -628,20 +603,28 @@ * @param val the json_object to be added */ JSON_EXPORT int json_object_array_put_idx(struct json_object *obj, size_t idx, - struct json_object *val); + struct json_object *val); -/** Get the element at specificed index of the array (a json_object of type json_type_array) +/** Get the element at specified index of array `obj` (which must be a json_object of type json_type_array) + * + * *No* reference counts will be changed, and ownership of the returned + * object remains with `obj`. See json_object_object_get() for additional + * implications of this behavior. + * + * Calling this with anything other than a json_type_array will trigger + * an assert. + * * @param obj the json_object instance * @param idx the index to get the element at * @returns the json_object at the specified index (or NULL) */ -JSON_EXPORT struct json_object* json_object_array_get_idx(const struct json_object *obj, - size_t idx); +JSON_EXPORT struct json_object *json_object_array_get_idx(const struct json_object *obj, + size_t idx); /** Delete an elements from a specified index in an array (a json_object of type json_type_array) * * The reference count will be decremented for each of the deleted objects. If there - * are no more owners of an element that is being deleted, then the value is + * are no more owners of an element that is being deleted, then the value is * freed. Otherwise, the reference to the value will remain in memory. * * @param obj the json_object instance @@ -651,40 +634,47 @@ */ JSON_EXPORT int json_object_array_del_idx(struct json_object *obj, size_t idx, size_t count); +/** + * Shrink the internal memory allocation of the array to just + * enough to fit the number of elements in it, plus empty_slots. + * + * @param jso the json_object instance, must be json_type_array + * @param empty_slots the number of empty slots to leave allocated + */ +JSON_EXPORT int json_object_array_shrink(struct json_object *jso, int empty_slots); + /* json_bool type methods */ /** Create a new empty json_object of type json_type_boolean - * @param b a json_bool TRUE or FALSE (1 or 0) + * @param b a json_bool 1 or 0 * @returns a json_object of type json_type_boolean */ -JSON_EXPORT struct json_object* json_object_new_boolean(json_bool b); +JSON_EXPORT struct json_object *json_object_new_boolean(json_bool b); /** Get the json_bool value of a json_object * * The type is coerced to a json_bool if the passed object is not a json_bool. - * integer and double objects will return FALSE if there value is zero - * or TRUE otherwise. If the passed object is a string it will return - * TRUE if it has a non zero length. If any other object type is passed - * TRUE will be returned if the object is not NULL. + * integer and double objects will return 0 if there value is zero + * or 1 otherwise. If the passed object is a string it will return + * 1 if it has a non zero length. If any other object type is passed + * 1 will be returned if the object is not NULL. * * @param obj the json_object instance * @returns a json_bool */ JSON_EXPORT json_bool json_object_get_boolean(const struct json_object *obj); - /** Set the json_bool value of a json_object - * - * The type of obj is checked to be a json_type_boolean and 0 is returned + * + * The type of obj is checked to be a json_type_boolean and 0 is returned * if it is not without any further actions. If type of obj is json_type_boolean - * the obect value is chaned to new_value + * the object value is changed to new_value * * @param obj the json_object instance * @param new_value the value to be set * @returns 1 if value is set correctly, 0 otherwise */ -JSON_EXPORT int json_object_set_boolean(struct json_object *obj,json_bool new_value); - +JSON_EXPORT int json_object_set_boolean(struct json_object *obj, json_bool new_value); /* int type methods */ @@ -694,15 +684,19 @@ * @param i the integer * @returns a json_object of type json_type_int */ -JSON_EXPORT struct json_object* json_object_new_int(int32_t i); - +JSON_EXPORT struct json_object *json_object_new_int(int32_t i); /** Create a new empty json_object of type json_type_int * @param i the integer * @returns a json_object of type json_type_int */ -JSON_EXPORT struct json_object* json_object_new_int64(int64_t i); +JSON_EXPORT struct json_object *json_object_new_int64(int64_t i); +/** Create a new empty json_object of type json_type_uint + * @param i the integer + * @returns a json_object of type json_type_uint + */ +JSON_EXPORT struct json_object *json_object_new_uint64(uint64_t i); /** Get the int value of a json_object * @@ -721,16 +715,16 @@ JSON_EXPORT int32_t json_object_get_int(const struct json_object *obj); /** Set the int value of a json_object - * - * The type of obj is checked to be a json_type_int and 0 is returned + * + * The type of obj is checked to be a json_type_int and 0 is returned * if it is not without any further actions. If type of obj is json_type_int - * the obect value is changed to new_value + * the object value is changed to new_value * * @param obj the json_object instance * @param new_value the value to be set * @returns 1 if value is set correctly, 0 otherwise */ -JSON_EXPORT int json_object_set_int(struct json_object *obj,int new_value); +JSON_EXPORT int json_object_set_int(struct json_object *obj, int new_value); /** Increment a json_type_int object by the given amount, which may be negative. * @@ -748,7 +742,6 @@ */ JSON_EXPORT int json_object_int_inc(struct json_object *obj, int64_t val); - /** Get the int value of a json_object * * The type is coerced to a int64 if the passed object is not a int64. @@ -764,18 +757,44 @@ */ JSON_EXPORT int64_t json_object_get_int64(const struct json_object *obj); +/** Get the uint value of a json_object + * + * The type is coerced to a uint64 if the passed object is not a uint64. + * double objects will return their uint64 conversion. Strings will be + * parsed as an uint64. If no conversion exists then 0 is returned. + * + * NOTE: Set errno to 0 directly before a call to this function to determine + * whether or not conversion was successful (it does not clear the value for + * you). + * + * @param obj the json_object instance + * @returns an uint64 + */ +JSON_EXPORT uint64_t json_object_get_uint64(const struct json_object *obj); /** Set the int64_t value of a json_object - * - * The type of obj is checked to be a json_type_int and 0 is returned + * + * The type of obj is checked to be a json_type_int and 0 is returned * if it is not without any further actions. If type of obj is json_type_int - * the obect value is chaned to new_value + * the object value is changed to new_value * * @param obj the json_object instance * @param new_value the value to be set * @returns 1 if value is set correctly, 0 otherwise */ -JSON_EXPORT int json_object_set_int64(struct json_object *obj,int64_t new_value); +JSON_EXPORT int json_object_set_int64(struct json_object *obj, int64_t new_value); + +/** Set the uint64_t value of a json_object + * + * The type of obj is checked to be a json_type_uint and 0 is returned + * if it is not without any further actions. If type of obj is json_type_uint + * the object value is changed to new_value + * + * @param obj the json_object instance + * @param new_value the value to be set + * @returns 1 if value is set correctly, 0 otherwise + */ +JSON_EXPORT int json_object_set_uint64(struct json_object *obj, uint64_t new_value); /* double type methods */ @@ -786,7 +805,7 @@ * @param d the double * @returns a json_object of type json_type_double */ -JSON_EXPORT struct json_object* json_object_new_double(double d); +JSON_EXPORT struct json_object *json_object_new_double(double d); /** * Create a new json_object of type json_type_double, using @@ -804,7 +823,8 @@ * The userdata field is used to store the string representation, so it * can't be used for other data if this function is used. * - * An equivalent sequence of calls is: + * A roughly equivalent sequence of calls, with the difference being that + * the serialization function won't be reset by json_object_set_double(), is: * @code * jso = json_object_new_double(d); * json_object_set_serializer(jso, json_object_userdata_to_json_string, @@ -814,7 +834,7 @@ * @param d the numeric value of the double. * @param ds the string representation of the double. This will be copied. */ -JSON_EXPORT struct json_object* json_object_new_double_s(double d, const char *ds); +JSON_EXPORT struct json_object *json_object_new_double_s(double d, const char *ds); /** * Set a global or thread-local json-c option, depending on whether @@ -828,9 +848,8 @@ * * @return -1 on errors, 0 on success. */ -int json_c_set_serialization_double_format(const char *double_format, int global_or_thread); - - +JSON_EXPORT int json_c_set_serialization_double_format(const char *double_format, + int global_or_thread); /** Serialize a json_object of type json_type_double to a string. * @@ -851,10 +870,8 @@ * @param level Ignored. * @param flags Ignored. */ -JSON_EXPORT int json_object_double_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, - int flags); +JSON_EXPORT int json_object_double_to_json_string(struct json_object *jso, struct printbuf *pb, + int level, int flags); /** Get the double floating point value of a json_object * @@ -881,20 +898,20 @@ */ JSON_EXPORT double json_object_get_double(const struct json_object *obj); - /** Set the double value of a json_object - * - * The type of obj is checked to be a json_type_double and 0 is returned + * + * The type of obj is checked to be a json_type_double and 0 is returned * if it is not without any further actions. If type of obj is json_type_double - * the obect value is chaned to new_value + * the object value is changed to new_value + * + * If the object was created with json_object_new_double_s(), the serialization + * function is reset to the default and the cached serialized value is cleared. * * @param obj the json_object instance * @param new_value the value to be set * @returns 1 if value is set correctly, 0 otherwise */ -JSON_EXPORT int json_object_set_double(struct json_object *obj,double new_value); - - +JSON_EXPORT int json_object_set_double(struct json_object *obj, double new_value); /* string type methods */ @@ -904,10 +921,21 @@ * * @param s the string * @returns a json_object of type json_type_string + * @see json_object_new_string_len() */ -JSON_EXPORT struct json_object* json_object_new_string(const char *s); +JSON_EXPORT struct json_object *json_object_new_string(const char *s); -JSON_EXPORT struct json_object* json_object_new_string_len(const char *s, int len); +/** Create a new empty json_object of type json_type_string and allocate + * len characters for the new string. + * + * A copy of the string is made and the memory is managed by the json_object + * + * @param s the string + * @param len max length of the new string + * @returns a json_object of type json_type_string + * @see json_object_new_string() + */ +JSON_EXPORT struct json_object *json_object_new_string_len(const char *s, const int len); /** Get the string value of a json_object * @@ -925,7 +953,7 @@ * @param obj the json_object instance * @returns a string or NULL */ -JSON_EXPORT const char* json_object_get_string(struct json_object *obj); +JSON_EXPORT const char *json_object_get_string(struct json_object *obj); /** Get the string length of a json_object * @@ -937,25 +965,30 @@ */ JSON_EXPORT int json_object_get_string_len(const struct json_object *obj); - /** Set the string value of a json_object with zero terminated strings * equivalent to json_object_set_string_len (obj, new_value, strlen(new_value)) * @returns 1 if value is set correctly, 0 otherwise */ -JSON_EXPORT int json_object_set_string(json_object* obj, const char* new_value); +JSON_EXPORT int json_object_set_string(json_object *obj, const char *new_value); /** Set the string value of a json_object str - * - * The type of obj is checked to be a json_type_string and 0 is returned + * + * The type of obj is checked to be a json_type_string and 0 is returned * if it is not without any further actions. If type of obj is json_type_string - * the obect value is chaned to new_value + * the object value is changed to new_value * * @param obj the json_object instance - * @param new_value the value to be set; Since string legth is given in len this need not be zero terminated + * @param new_value the value to be set; Since string length is given in len this need not be zero terminated * @param len the length of new_value * @returns 1 if value is set correctly, 0 otherwise */ -JSON_EXPORT int json_object_set_string_len(json_object* obj, const char* new_value, int len); +JSON_EXPORT int json_object_set_string_len(json_object *obj, const char *new_value, int len); + +/** This method exists only to provide a complementary function + * along the lines of the other json_object_new_* functions. + * It always returns NULL, and it is entirely acceptable to simply use NULL directly. + */ +JSON_EXPORT struct json_object *json_object_new_null(void); /** Check if two json_object's are equal * @@ -974,8 +1007,7 @@ * @param obj2 the second json_object instance * @returns whether both objects are equal or not */ -JSON_EXPORT int json_object_equal(struct json_object *obj1, - struct json_object *obj2); +JSON_EXPORT int json_object_equal(struct json_object *obj1, struct json_object *obj2); /** * Perform a shallow copy of src into *dst as part of an overall json_object_deep_copy(). @@ -985,17 +1017,18 @@ * When shallow_copy is called *dst will be NULL, and must be non-NULL when it returns. * src will never be NULL. * - * If shallow_copy sets the serializer on an object, return 2 to indicate to + * If shallow_copy sets the serializer on an object, return 2 to indicate to * json_object_deep_copy that it should not attempt to use the standard userdata * copy function. * * @return On success 1 or 2, -1 on errors */ -typedef int (json_c_shallow_copy_fn)(json_object *src, json_object *parent, const char *key, size_t index, json_object **dst); +typedef int(json_c_shallow_copy_fn)(json_object *src, json_object *parent, const char *key, + size_t index, json_object **dst); /** * The default shallow copy implementation for use with json_object_deep_copy(). - * This simply calls the appropriate json_object_new_() function and + * This simply calls the appropriate json_object_new_() function and * copies over the serializer function (_to_json_string internal field of * the json_object structure) but not any _userdata or _user_delete values. * @@ -1005,7 +1038,7 @@ * * @return 1 on success, -1 on errors, but never 2. */ -json_c_shallow_copy_fn json_c_shallow_copy_default; +JSON_EXPORT json_c_shallow_copy_fn json_c_shallow_copy_default; /** * Copy the contents of the JSON object. @@ -1026,7 +1059,8 @@ * or if the destination pointer is non-NULL */ -JSON_EXPORT int json_object_deep_copy(struct json_object *src, struct json_object **dst, json_c_shallow_copy_fn *shallow_copy); +JSON_EXPORT int json_object_deep_copy(struct json_object *src, struct json_object **dst, + json_c_shallow_copy_fn *shallow_copy); #ifdef __cplusplus } #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_object_iterator.c thunderbird-91.8.1+build1/comm/third_party/json-c/json_object_iterator.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_object_iterator.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_object_iterator.c 2022-04-15 07:49:21.000000000 +0000 @@ -9,6 +9,7 @@ * ******************************************************************************* */ +#include "config.h" #include @@ -53,111 +54,100 @@ /// Our current representation of the "end" iterator; /// /// @note May not always be NULL -static const void* kObjectEndIterValue = NULL; +static const void *kObjectEndIterValue = NULL; /** * **************************************************************************** */ -struct json_object_iterator -json_object_iter_begin(struct json_object* obj) +struct json_object_iterator json_object_iter_begin(struct json_object *obj) { - struct json_object_iterator iter; - struct lh_table* pTable; + struct json_object_iterator iter; + struct lh_table *pTable; - /// @note json_object_get_object will return NULL if passed NULL - /// or a non-json_type_object instance - pTable = json_object_get_object(obj); - JASSERT(NULL != pTable); + /// @note json_object_get_object will return NULL if passed NULL + /// or a non-json_type_object instance + pTable = json_object_get_object(obj); + JASSERT(NULL != pTable); - /// @note For a pair-less Object, head is NULL, which matches our - /// definition of the "end" iterator - iter.opaque_ = pTable->head; - return iter; + /// @note For a pair-less Object, head is NULL, which matches our + /// definition of the "end" iterator + iter.opaque_ = pTable->head; + return iter; } /** * **************************************************************************** */ -struct json_object_iterator -json_object_iter_end(const struct json_object* obj) +struct json_object_iterator json_object_iter_end(const struct json_object *obj) { - struct json_object_iterator iter; + struct json_object_iterator iter; - JASSERT(NULL != obj); - JASSERT(json_object_is_type(obj, json_type_object)); + JASSERT(NULL != obj); + JASSERT(json_object_is_type(obj, json_type_object)); - iter.opaque_ = kObjectEndIterValue; + iter.opaque_ = kObjectEndIterValue; - return iter; + return iter; } /** * **************************************************************************** */ -void -json_object_iter_next(struct json_object_iterator* iter) +void json_object_iter_next(struct json_object_iterator *iter) { - JASSERT(NULL != iter); - JASSERT(kObjectEndIterValue != iter->opaque_); + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); - iter->opaque_ = ((const struct lh_entry *)iter->opaque_)->next; + iter->opaque_ = ((const struct lh_entry *)iter->opaque_)->next; } - /** * **************************************************************************** */ -const char* -json_object_iter_peek_name(const struct json_object_iterator* iter) +const char *json_object_iter_peek_name(const struct json_object_iterator *iter) { - JASSERT(NULL != iter); - JASSERT(kObjectEndIterValue != iter->opaque_); + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); - return (const char*)(((const struct lh_entry *)iter->opaque_)->k); + return (const char *)(((const struct lh_entry *)iter->opaque_)->k); } - /** * **************************************************************************** */ -struct json_object* -json_object_iter_peek_value(const struct json_object_iterator* iter) +struct json_object *json_object_iter_peek_value(const struct json_object_iterator *iter) { - JASSERT(NULL != iter); - JASSERT(kObjectEndIterValue != iter->opaque_); + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); - return (struct json_object*)lh_entry_v((const struct lh_entry *)iter->opaque_); + return (struct json_object *)lh_entry_v((const struct lh_entry *)iter->opaque_); } - /** * **************************************************************************** */ -json_bool -json_object_iter_equal(const struct json_object_iterator* iter1, - const struct json_object_iterator* iter2) +json_bool json_object_iter_equal(const struct json_object_iterator *iter1, + const struct json_object_iterator *iter2) { - JASSERT(NULL != iter1); - JASSERT(NULL != iter2); + JASSERT(NULL != iter1); + JASSERT(NULL != iter2); - return (iter1->opaque_ == iter2->opaque_); + return (iter1->opaque_ == iter2->opaque_); } - /** * **************************************************************************** */ -struct json_object_iterator -json_object_iter_init_default(void) +struct json_object_iterator json_object_iter_init_default(void) { - struct json_object_iterator iter; + struct json_object_iterator iter; - /** - * @note Make this a negative, invalid value, such that - * accidental access to it would likely be trapped by the - * hardware as an invalid address. - */ - iter.opaque_ = NULL; + /** + * @note Make this a negative, invalid value, such that + * accidental access to it would likely be trapped by the + * hardware as an invalid address. + */ + iter.opaque_ = NULL; - return iter; + return iter; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_object_iterator.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_object_iterator.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_object_iterator.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_object_iterator.h 2022-04-15 07:49:21.000000000 +0000 @@ -20,10 +20,10 @@ ******************************************************************************* */ - #ifndef JSON_OBJECT_ITERATOR_H #define JSON_OBJECT_ITERATOR_H +#include "json_types.h" #include #ifdef __cplusplus @@ -39,17 +39,16 @@ * The opaque iterator that references a name/value pair within * a JSON Object instance or the "end" iterator value. */ -struct json_object_iterator { - const void* opaque_; +struct json_object_iterator +{ + const void *opaque_; }; - /** * forward declaration of json-c's JSON value instance structure */ struct json_object; - /** * Initializes an iterator structure to a "default" value that * is convenient for initializing an iterator variable to a @@ -72,8 +71,7 @@ * * @return json_object_iterator */ -struct json_object_iterator -json_object_iter_init_default(void); +JSON_EXPORT struct json_object_iterator json_object_iter_init_default(void); /** Retrieves an iterator to the first pair of the JSON Object. * @@ -106,8 +104,7 @@ * * @endcode */ -struct json_object_iterator -json_object_iter_begin(struct json_object* obj); +JSON_EXPORT struct json_object_iterator json_object_iter_begin(struct json_object *obj); /** Retrieves the iterator that represents the position beyond the * last pair of the given JSON Object instance. @@ -137,8 +134,7 @@ * (i.e., NOT the last pair, but "beyond the last * pair" value) */ -struct json_object_iterator -json_object_iter_end(const struct json_object* obj); +JSON_EXPORT struct json_object_iterator json_object_iter_end(const struct json_object *obj); /** Returns an iterator to the next pair, if any * @@ -155,9 +151,7 @@ * of json_object_iter_end() for the same JSON Object * instance. */ -void -json_object_iter_next(struct json_object_iterator* iter); - +JSON_EXPORT void json_object_iter_next(struct json_object_iterator *iter); /** Returns a const pointer to the name of the pair referenced * by the given iterator. @@ -174,9 +168,7 @@ * deleted or modified, and MUST NOT be modified or * freed by the user. */ -const char* -json_object_iter_peek_name(const struct json_object_iterator* iter); - +JSON_EXPORT const char *json_object_iter_peek_name(const struct json_object_iterator *iter); /** Returns a pointer to the json-c instance representing the * value of the referenced name/value pair, without altering @@ -197,9 +189,8 @@ * the JSON Null value as a NULL json_object instance * pointer. */ -struct json_object* -json_object_iter_peek_value(const struct json_object_iterator* iter); - +JSON_EXPORT struct json_object * +json_object_iter_peek_value(const struct json_object_iterator *iter); /** Tests two iterators for equality. Typically used to test * for end of iteration by comparing an iterator to the @@ -227,14 +218,11 @@ * reference the same name/value pair or are both at * "end"); zero if they are not equal. */ -json_bool -json_object_iter_equal(const struct json_object_iterator* iter1, - const struct json_object_iterator* iter2); - +JSON_EXPORT json_bool json_object_iter_equal(const struct json_object_iterator *iter1, + const struct json_object_iterator *iter2); #ifdef __cplusplus } #endif - #endif /* JSON_OBJECT_ITERATOR_H */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_object_private.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_object_private.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_object_private.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_object_private.h 2022-04-15 07:49:21.000000000 +0000 @@ -20,41 +20,84 @@ extern "C" { #endif -#define LEN_DIRECT_STRING_DATA 32 /**< how many bytes are directly stored in json_object for strings? */ +struct json_object; +#include "json_inttypes.h" +#include "json_types.h" + +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ + +#ifdef _MSC_VER +#include +typedef SSIZE_T ssize_t; +#endif -typedef void (json_object_private_delete_fn)(struct json_object *o); +/* json object int type, support extension*/ +typedef enum json_object_int_type +{ + json_object_int_type_int64, + json_object_int_type_uint64 +} json_object_int_type; struct json_object { - enum json_type o_type; - json_object_private_delete_fn *_delete; - json_object_to_json_string_fn *_to_json_string; - int _ref_count; - struct printbuf *_pb; - union data { - json_bool c_boolean; - double c_double; - int64_t c_int64; - struct lh_table *c_object; - struct array_list *c_array; - struct { - union { - /* optimize: if we have small strings, we can store them - * directly. This saves considerable CPU cycles AND memory. - */ - char *ptr; - char data[LEN_DIRECT_STRING_DATA]; - } str; - int len; - } c_string; - } o; - json_object_delete_fn *_user_delete; - void *_userdata; + enum json_type o_type; + uint32_t _ref_count; + json_object_to_json_string_fn *_to_json_string; + struct printbuf *_pb; + json_object_delete_fn *_user_delete; + void *_userdata; + // Actually longer, always malloc'd as some more-specific type. + // The rest of a struct json_object_${o_type} follows +}; + +struct json_object_object +{ + struct json_object base; + struct lh_table *c_object; +}; +struct json_object_array +{ + struct json_object base; + struct array_list *c_array; +}; + +struct json_object_boolean +{ + struct json_object base; + json_bool c_boolean; +}; +struct json_object_double +{ + struct json_object base; + double c_double; +}; +struct json_object_int +{ + struct json_object base; + enum json_object_int_type cint_type; + union + { + int64_t c_int64; + uint64_t c_uint64; + } cint; +}; +struct json_object_string +{ + struct json_object base; + ssize_t len; // Signed b/c negative lengths indicate data is a pointer + // Consider adding an "alloc" field here, if json_object_set_string calls + // to expand the length of a string are common operations to perform. + union + { + char idata[1]; // Immediate data. Actually longer + char *pdata; // Only when len < 0 + } c_string; }; void _json_c_set_last_err(const char *err_fmt, ...); -extern const char *json_number_chars; extern const char *json_hex_chars; #ifdef __cplusplus diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_pointer.c thunderbird-91.8.1+build1/comm/third_party/json-c/json_pointer.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_pointer.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_pointer.c 2022-04-15 07:49:21.000000000 +0000 @@ -10,11 +10,11 @@ #include "strerror_override.h" +#include #include #include #include #include -#include #include "json_pointer.h" #include "strdup_compat.h" @@ -28,9 +28,10 @@ static void string_replace_all_occurrences_with_char(char *s, const char *occur, char repl_char) { int slen = strlen(s); - int skip = strlen(occur) - 1; /* length of the occurence, minus the char we're replacing */ + int skip = strlen(occur) - 1; /* length of the occurrence, minus the char we're replacing */ char *p = s; - while ((p = strstr(p, occur))) { + while ((p = strstr(p, occur))) + { *p = repl_char; p++; slen -= skip; @@ -41,10 +42,13 @@ static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx) { int i, len = strlen(path); - /* this code-path optimizes a bit, for when we reference the 0-9 index range in a JSON array - and because leading zeros not allowed */ - if (len == 1) { - if (isdigit((int)path[0])) { + /* this code-path optimizes a bit, for when we reference the 0-9 index range + * in a JSON array and because leading zeros not allowed + */ + if (len == 1) + { + if (isdigit((unsigned char)path[0])) + { *idx = (path[0] - '0'); goto check_oob; } @@ -52,26 +56,31 @@ return 0; } /* leading zeros not allowed per RFC */ - if (path[0] == '0') { + if (path[0] == '0') + { errno = EINVAL; return 0; } /* RFC states base-10 decimals */ - for (i = 0; i < len; i++) { - if (!isdigit((int)path[i])) { + for (i = 0; i < len; i++) + { + if (!isdigit((unsigned char)path[i])) + { errno = EINVAL; return 0; } } *idx = strtol(path, NULL, 10); - if (*idx < 0) { + if (*idx < 0) + { errno = EINVAL; return 0; } check_oob: len = json_object_array_length(jo); - if (*idx >= len) { + if (*idx >= len) + { errno = ENOENT; return 0; } @@ -79,14 +88,17 @@ return 1; } -static int json_pointer_get_single_path(struct json_object *obj, char *path, struct json_object **value) +static int json_pointer_get_single_path(struct json_object *obj, char *path, + struct json_object **value) { - if (json_object_is_type(obj, json_type_array)) { + if (json_object_is_type(obj, json_type_array)) + { int32_t idx; if (!is_valid_index(obj, path, &idx)) return -1; obj = json_object_array_get_idx(obj, idx); - if (obj) { + if (obj) + { if (value) *value = obj; return 0; @@ -100,7 +112,8 @@ string_replace_all_occurrences_with_char(path, "~1", '/'); string_replace_all_occurrences_with_char(path, "~0", '~'); - if (!json_object_object_get_ex(obj, path, value)) { + if (!json_object_object_get_ex(obj, path, value)) + { errno = ENOENT; return -1; } @@ -108,12 +121,11 @@ return 0; } -static int json_pointer_set_single_path( - struct json_object *parent, - const char *path, - struct json_object *value) +static int json_pointer_set_single_path(struct json_object *parent, const char *path, + struct json_object *value) { - if (json_object_is_type(parent, json_type_array)) { + if (json_object_is_type(parent, json_type_array)) + { int32_t idx; /* RFC (Chapter 4) states that '-' may be used to add new elements to an array */ if (path[0] == '-' && path[1] == '\0') @@ -124,26 +136,27 @@ } /* path replacements should have been done in json_pointer_get_single_path(), - and we should still be good here */ + * and we should still be good here + */ if (json_object_is_type(parent, json_type_object)) return json_object_object_add(parent, path, value); - /* Getting here means that we tried to "dereference" a primitive JSON type (like string, int, bool). - i.e. add a sub-object to it */ + /* Getting here means that we tried to "dereference" a primitive JSON type + * (like string, int, bool).i.e. add a sub-object to it + */ errno = ENOENT; return -1; } -static int json_pointer_get_recursive( - struct json_object *obj, - char *path, - struct json_object **value) +static int json_pointer_get_recursive(struct json_object *obj, char *path, + struct json_object **value) { char *endp; int rc; /* All paths (on each recursion level must have a leading '/' */ - if (path[0] != '/') { + if (path[0] != '/') + { errno = EINVAL; return -1; } @@ -157,8 +170,10 @@ if ((rc = json_pointer_get_single_path(obj, path, &obj))) return rc; - if (endp) { - *endp = '/'; /* Put the slash back, so that the sanity check passes on next recursion level */ + if (endp) + { + /* Put the slash back, so that the sanity check passes on next recursion level */ + *endp = '/'; return json_pointer_get_recursive(obj, endp, value); } @@ -174,19 +189,22 @@ char *path_copy = NULL; int rc; - if (!obj || !path) { + if (!obj || !path) + { errno = EINVAL; return -1; } - if (path[0] == '\0') { + if (path[0] == '\0') + { if (res) *res = obj; return 0; } /* pass a working copy to the recursive call */ - if (!(path_copy = strdup(path))) { + if (!(path_copy = strdup(path))) + { errno = ENOMEM; return -1; } @@ -202,7 +220,8 @@ int rc = 0; va_list args; - if (!obj || !path_fmt) { + if (!obj || !path_fmt) + { errno = EINVAL; return -1; } @@ -214,7 +233,8 @@ if (rc < 0) return rc; - if (path_copy[0] == '\0') { + if (path_copy[0] == '\0') + { if (res) *res = obj; goto out; @@ -234,30 +254,35 @@ struct json_object *set = NULL; int rc; - if (!obj || !path) { + if (!obj || !path) + { errno = EINVAL; return -1; } - if (path[0] == '\0') { + if (path[0] == '\0') + { json_object_put(*obj); *obj = value; return 0; } - if (path[0] != '/') { + if (path[0] != '/') + { errno = EINVAL; return -1; } /* If there's only 1 level to set, stop here */ - if ((endp = strrchr(path, '/')) == path) { + if ((endp = strrchr(path, '/')) == path) + { path++; return json_pointer_set_single_path(*obj, path, value); } /* pass a working copy to the recursive call */ - if (!(path_copy = strdup(path))) { + if (!(path_copy = strdup(path))) + { errno = ENOMEM; return -1; } @@ -272,7 +297,8 @@ return json_pointer_set_single_path(set, endp, value); } -int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...) +int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, + ...) { char *endp; char *path_copy = NULL; @@ -280,7 +306,8 @@ va_list args; int rc = 0; - if (!obj || !path_fmt) { + if (!obj || !path_fmt) + { errno = EINVAL; return -1; } @@ -293,20 +320,23 @@ if (rc < 0) return rc; - if (path_copy[0] == '\0') { + if (path_copy[0] == '\0') + { json_object_put(*obj); *obj = value; goto out; } - if (path_copy[0] != '/') { + if (path_copy[0] != '/') + { errno = EINVAL; rc = -1; goto out; } /* If there's only 1 level to set, stop here */ - if ((endp = strrchr(path_copy, '/')) == path_copy) { + if ((endp = strrchr(path_copy, '/')) == path_copy) + { set = *obj; goto set_single_path; } @@ -324,4 +354,3 @@ free(path_copy); return rc; } - diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_pointer.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_pointer.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_pointer.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_pointer.h 2022-04-15 07:49:21.000000000 +0000 @@ -39,12 +39,13 @@ * * @param obj the json_object instance/tree from where to retrieve sub-objects * @param path a (RFC6901) string notation for the sub-object to retrieve - * @param res a pointer where to store a reference to the json_object + * @param res a pointer that stores a reference to the json_object * associated with the given path * * @return negative if an error (or not found), or 0 if succeeded */ -int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res); +JSON_EXPORT int json_pointer_get(struct json_object *obj, const char *path, + struct json_object **res); /** * This is a variant of 'json_pointer_get()' that supports printf() style arguments. @@ -56,13 +57,14 @@ * aspects when using this function. * * @param obj the json_object instance/tree to which to add a sub-object - * @param res a pointer where to store a reference to the json_object + * @param res a pointer that stores a reference to the json_object * associated with the given path * @param path_fmt a printf() style format for the path * * @return negative if an error (or not found), or 0 if succeeded */ -int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...); +JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **res, + const char *path_fmt, ...); /** * Sets JSON object 'value' in the 'obj' tree at the location specified @@ -93,7 +95,8 @@ * * @return negative if an error (or not found), or 0 if succeeded */ -int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value); +JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path, + struct json_object *value); /** * This is a variant of 'json_pointer_set()' that supports printf() style arguments. @@ -110,8 +113,8 @@ * * @return negative if an error (or not found), or 0 if succeeded */ -int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...); - +JSON_EXPORT int json_pointer_setf(struct json_object **obj, struct json_object *value, + const char *path_fmt, ...); #ifdef __cplusplus } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_tokener.c thunderbird-91.8.1+build1/comm/third_party/json-c/json_tokener.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_tokener.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_tokener.c 2022-04-15 07:49:21.000000000 +0000 @@ -15,23 +15,23 @@ #include "config.h" -#include #include "math_compat.h" +#include +#include +#include +#include +#include #include #include -#include -#include #include -#include #include "debug.h" -#include "printbuf.h" -#include "arraylist.h" #include "json_inttypes.h" #include "json_object.h" #include "json_object_private.h" #include "json_tokener.h" #include "json_util.h" +#include "printbuf.h" #include "strdup_compat.h" #ifdef HAVE_LOCALE_H @@ -40,14 +40,17 @@ #ifdef HAVE_XLOCALE_H #include #endif +#ifdef HAVE_STRINGS_H +#include +#endif /* HAVE_STRINGS_H */ -#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) +#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9) #if !HAVE_STRNCASECMP && defined(_MSC_VER) - /* MSC has the version as _strnicmp */ -# define strncasecmp _strnicmp +/* MSC has the version as _strnicmp */ +#define strncasecmp _strnicmp #elif !HAVE_STRNCASECMP -# error You do not have strncasecmp on your system. +#error You do not have strncasecmp on your system. #endif /* HAVE_STRNCASECMP */ /* Use C99 NAN by default; if not available, nan("") should work too. */ @@ -67,27 +70,38 @@ static const char json_false_str[] = "false"; static const int json_false_str_len = sizeof(json_false_str) - 1; -static const char* json_tokener_errors[] = { - "success", - "continue", - "nesting too deep", - "unexpected end of data", - "unexpected character", - "null expected", - "boolean expected", - "number expected", - "array value separator ',' expected", - "quoted object property name expected", - "object property name separator ':' expected", - "object value separator ',' expected", - "invalid string sequence", - "expected comment", - "buffer size overflow" +/* clang-format off */ +static const char *json_tokener_errors[] = { + "success", + "continue", + "nesting too deep", + "unexpected end of data", + "unexpected character", + "null expected", + "boolean expected", + "number expected", + "array value separator ',' expected", + "quoted object property name expected", + "object property name separator ':' expected", + "object value separator ',' expected", + "invalid string sequence", + "expected comment", + "invalid utf-8 string", + "buffer size overflow" }; +/* clang-format on */ + +/** + * validete the utf-8 string in strict model. + * if not utf-8 format, return err. + */ +static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes); + +static int json_tokener_parse_double(const char *buf, int len, double *retval); const char *json_tokener_error_desc(enum json_tokener_error jerr) { - int jerr_int = (int) jerr; + int jerr_int = (int)jerr; if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0]))) return "Unknown error, " @@ -101,95 +115,107 @@ } /* Stuff for decoding unicode sequences */ -#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800) -#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00) -#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000) -static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD }; - -struct json_tokener* json_tokener_new_ex(int depth) -{ - struct json_tokener *tok; - - tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener)); - if (!tok) return NULL; - tok->stack = (struct json_tokener_srec *) calloc(depth, - sizeof(struct json_tokener_srec)); - if (!tok->stack) { - free(tok); - return NULL; - } - tok->pb = printbuf_new(); - tok->max_depth = depth; - json_tokener_reset(tok); - return tok; +#define IS_HIGH_SURROGATE(uc) (((uc)&0xFC00) == 0xD800) +#define IS_LOW_SURROGATE(uc) (((uc)&0xFC00) == 0xDC00) +#define DECODE_SURROGATE_PAIR(hi, lo) ((((hi)&0x3FF) << 10) + ((lo)&0x3FF) + 0x10000) +static unsigned char utf8_replacement_char[3] = {0xEF, 0xBF, 0xBD}; + +struct json_tokener *json_tokener_new_ex(int depth) +{ + struct json_tokener *tok; + + tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener)); + if (!tok) + return NULL; + tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec)); + if (!tok->stack) + { + free(tok); + return NULL; + } + tok->pb = printbuf_new(); + tok->max_depth = depth; + json_tokener_reset(tok); + return tok; } -struct json_tokener* json_tokener_new(void) +struct json_tokener *json_tokener_new(void) { - return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH); + return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH); } void json_tokener_free(struct json_tokener *tok) { - json_tokener_reset(tok); - if (tok->pb) printbuf_free(tok->pb); - free(tok->stack); - free(tok); + json_tokener_reset(tok); + if (tok->pb) + printbuf_free(tok->pb); + free(tok->stack); + free(tok); } static void json_tokener_reset_level(struct json_tokener *tok, int depth) { - tok->stack[depth].state = json_tokener_state_eatws; - tok->stack[depth].saved_state = json_tokener_state_start; - json_object_put(tok->stack[depth].current); - tok->stack[depth].current = NULL; - free(tok->stack[depth].obj_field_name); - tok->stack[depth].obj_field_name = NULL; + tok->stack[depth].state = json_tokener_state_eatws; + tok->stack[depth].saved_state = json_tokener_state_start; + json_object_put(tok->stack[depth].current); + tok->stack[depth].current = NULL; + free(tok->stack[depth].obj_field_name); + tok->stack[depth].obj_field_name = NULL; } void json_tokener_reset(struct json_tokener *tok) { - int i; - if (!tok) - return; - - for(i = tok->depth; i >= 0; i--) - json_tokener_reset_level(tok, i); - tok->depth = 0; - tok->err = json_tokener_success; + int i; + if (!tok) + return; + + for (i = tok->depth; i >= 0; i--) + json_tokener_reset_level(tok, i); + tok->depth = 0; + tok->err = json_tokener_success; } -struct json_object* json_tokener_parse(const char *str) +struct json_object *json_tokener_parse(const char *str) { - enum json_tokener_error jerr_ignored; - struct json_object* obj; - obj = json_tokener_parse_verbose(str, &jerr_ignored); - return obj; + enum json_tokener_error jerr_ignored; + struct json_object *obj; + obj = json_tokener_parse_verbose(str, &jerr_ignored); + return obj; } -struct json_object* json_tokener_parse_verbose(const char *str, - enum json_tokener_error *error) +struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error) { - struct json_tokener* tok; - struct json_object* obj; + struct json_tokener *tok; + struct json_object *obj; - tok = json_tokener_new(); - if (!tok) - return NULL; - obj = json_tokener_parse_ex(tok, str, -1); - *error = tok->err; - if(tok->err != json_tokener_success) { + tok = json_tokener_new(); + if (!tok) + return NULL; + obj = json_tokener_parse_ex(tok, str, -1); + *error = tok->err; + if (tok->err != json_tokener_success +#if 0 + /* This would be a more sensible default, and cause parsing + * things like "null123" to fail when the caller can't know + * where the parsing left off, but starting to fail would + * be a notable behaviour change. Save for a 1.0 release. + */ + || json_tokener_get_parse_end(tok) != strlen(str) +#endif + ) + + { if (obj != NULL) json_object_put(obj); - obj = NULL; - } + obj = NULL; + } - json_tokener_free(tok); - return obj; + json_tokener_free(tok); + return obj; } -#define state tok->stack[tok->depth].state -#define saved_state tok->stack[tok->depth].saved_state +#define state tok->stack[tok->depth].state +#define saved_state tok->stack[tok->depth].saved_state #define current tok->stack[tok->depth].current #define obj_field_name tok->stack[tok->depth].obj_field_name @@ -209,789 +235,1034 @@ /* PEEK_CHAR(dest, tok) macro: * Peeks at the current char and stores it in dest. * Returns 1 on success, sets tok->err and returns 0 if no more chars. - * Implicit inputs: str, len vars + * Implicit inputs: str, len, nBytesp vars */ -#define PEEK_CHAR(dest, tok) \ - (((tok)->char_offset == len) ? \ - (((tok)->depth == 0 && \ - state == json_tokener_state_eatws && \ - saved_state == json_tokener_state_finish \ - ) ? \ - (((tok)->err = json_tokener_success), 0) \ - : \ - (((tok)->err = json_tokener_continue), 0) \ - ) : \ - (((dest) = *str), 1) \ - ) +#define PEEK_CHAR(dest, tok) \ + (((tok)->char_offset == len) \ + ? (((tok)->depth == 0 && state == json_tokener_state_eatws && \ + saved_state == json_tokener_state_finish) \ + ? (((tok)->err = json_tokener_success), 0) \ + : (((tok)->err = json_tokener_continue), 0)) \ + : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && \ + (!json_tokener_validate_utf8(*str, nBytesp))) \ + ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \ + : (((dest) = *str), 1))) /* ADVANCE_CHAR() macro: - * Incrementes str & tok->char_offset. + * Increments str & tok->char_offset. * For convenience of existing conditionals, returns the old value of c (0 on eof) * Implicit inputs: c var */ -#define ADVANCE_CHAR(str, tok) \ - ( ++(str), ((tok)->char_offset)++, c) - +#define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c) /* End optimization macro defs */ - -struct json_object* json_tokener_parse_ex(struct json_tokener *tok, - const char *str, int len) +struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len) { - struct json_object *obj = NULL; - char c = '\1'; + struct json_object *obj = NULL; + char c = '\1'; + unsigned int nBytes = 0; + unsigned int *nBytesp = &nBytes; + #ifdef HAVE_USELOCALE - locale_t oldlocale = uselocale(NULL); - locale_t newloc; + locale_t oldlocale = uselocale(NULL); + locale_t newloc; #elif defined(HAVE_SETLOCALE) - char *oldlocale = NULL; + char *oldlocale = NULL; #endif - tok->char_offset = 0; - tok->err = json_tokener_success; + tok->char_offset = 0; + tok->err = json_tokener_success; - /* this interface is presently not 64-bit clean due to the int len argument - and the internal printbuf interface that takes 32-bit int len arguments - so the function limits the maximum string size to INT32_MAX (2GB). - If the function is called with len == -1 then strlen is called to check - the string length is less than INT32_MAX (2GB) */ - if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) { - tok->err = json_tokener_error_size; - return NULL; - } + /* this interface is presently not 64-bit clean due to the int len argument + * and the internal printbuf interface that takes 32-bit int len arguments + * so the function limits the maximum string size to INT32_MAX (2GB). + * If the function is called with len == -1 then strlen is called to check + * the string length is less than INT32_MAX (2GB) + */ + if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) + { + tok->err = json_tokener_error_size; + return NULL; + } #ifdef HAVE_USELOCALE - { - locale_t duploc = duplocale(oldlocale); - newloc = newlocale(LC_NUMERIC, "C", duploc); - // XXX at least Debian 8.4 has a bug in newlocale where it doesn't - // change the decimal separator unless you set LC_TIME! - if (newloc) - { - duploc = newloc; // original duploc has been freed by newlocale() - newloc = newlocale(LC_TIME, "C", duploc); - } - if (newloc == NULL) - { - freelocale(duploc); - return NULL; - } - uselocale(newloc); - } + { + locale_t duploc = duplocale(oldlocale); + newloc = newlocale(LC_NUMERIC_MASK, "C", duploc); + if (newloc == NULL) + { + freelocale(duploc); + return NULL; + } + uselocale(newloc); + } #elif defined(HAVE_SETLOCALE) - { - char *tmplocale; - tmplocale = setlocale(LC_NUMERIC, NULL); - if (tmplocale) oldlocale = strdup(tmplocale); - setlocale(LC_NUMERIC, "C"); - } + { + char *tmplocale; + tmplocale = setlocale(LC_NUMERIC, NULL); + if (tmplocale) + oldlocale = strdup(tmplocale); + setlocale(LC_NUMERIC, "C"); + } #endif - while (PEEK_CHAR(c, tok)) { + while (PEEK_CHAR(c, tok)) // Note: c might be '\0' ! + { - redo_char: - switch(state) { + redo_char: + switch (state) + { - case json_tokener_state_eatws: - /* Advance until we change state */ - while (isspace((int)c)) { - if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok))) - goto out; - } - if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) { - printbuf_reset(tok->pb); - printbuf_memappend_fast(tok->pb, &c, 1); - state = json_tokener_state_comment_start; - } else { - state = saved_state; - goto redo_char; - } - break; - - case json_tokener_state_start: - switch(c) { - case '{': - state = json_tokener_state_eatws; - saved_state = json_tokener_state_object_field_start; - current = json_object_new_object(); - if(current == NULL) - goto out; - break; - case '[': - state = json_tokener_state_eatws; - saved_state = json_tokener_state_array; - current = json_object_new_array(); - if(current == NULL) - goto out; - break; - case 'I': - case 'i': - state = json_tokener_state_inf; - printbuf_reset(tok->pb); - tok->st_pos = 0; - goto redo_char; - case 'N': - case 'n': - state = json_tokener_state_null; // or NaN - printbuf_reset(tok->pb); - tok->st_pos = 0; - goto redo_char; - case '\'': - if (tok->flags & JSON_TOKENER_STRICT) { - /* in STRICT mode only double-quote are allowed */ - tok->err = json_tokener_error_parse_unexpected; - goto out; - } - /* FALLTHRU */ - case '"': - state = json_tokener_state_string; - printbuf_reset(tok->pb); - tok->quote_char = c; - break; - case 'T': - case 't': - case 'F': - case 'f': - state = json_tokener_state_boolean; - printbuf_reset(tok->pb); - tok->st_pos = 0; - goto redo_char; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - state = json_tokener_state_number; - printbuf_reset(tok->pb); - tok->is_double = 0; - goto redo_char; - default: - tok->err = json_tokener_error_parse_unexpected; - goto out; - } - break; - - case json_tokener_state_finish: - if(tok->depth == 0) goto out; - obj = json_object_get(current); - json_tokener_reset_level(tok, tok->depth); - tok->depth--; - goto redo_char; - - case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */ - { - /* If we were guaranteed to have len set, then we could (usually) handle - * the entire "Infinity" check in a single strncmp (strncasecmp), but - * since len might be -1 (i.e. "read until \0"), we need to check it - * a character at a time. - * Trying to handle it both ways would make this code considerably more - * complicated with likely little performance benefit. - */ - int is_negative = 0; - const char *_json_inf_str = json_inf_str; - if (!(tok->flags & JSON_TOKENER_STRICT)) - _json_inf_str = json_inf_str_lower; - - /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */ - while (tok->st_pos < (int)json_inf_str_len) - { - char inf_char = *str; - if (!(tok->flags & JSON_TOKENER_STRICT)) - inf_char = tolower((int)*str); - if (inf_char != _json_inf_str[tok->st_pos]) + case json_tokener_state_eatws: + /* Advance until we change state */ + while (isspace((unsigned char)c)) + { + if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok))) + goto out; + } + if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) + { + printbuf_reset(tok->pb); + printbuf_memappend_fast(tok->pb, &c, 1); + state = json_tokener_state_comment_start; + } + else + { + state = saved_state; + goto redo_char; + } + break; + + case json_tokener_state_start: + switch (c) + { + case '{': + state = json_tokener_state_eatws; + saved_state = json_tokener_state_object_field_start; + current = json_object_new_object(); + if (current == NULL) + goto out; + break; + case '[': + state = json_tokener_state_eatws; + saved_state = json_tokener_state_array; + current = json_object_new_array(); + if (current == NULL) + goto out; + break; + case 'I': + case 'i': + state = json_tokener_state_inf; + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; + case 'N': + case 'n': + state = json_tokener_state_null; // or NaN + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; + case '\'': + if (tok->flags & JSON_TOKENER_STRICT) + { + /* in STRICT mode only double-quote are allowed */ + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + /* FALLTHRU */ + case '"': + state = json_tokener_state_string; + printbuf_reset(tok->pb); + tok->quote_char = c; + break; + case 'T': + case 't': + case 'F': + case 'f': + state = json_tokener_state_boolean; + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + state = json_tokener_state_number; + printbuf_reset(tok->pb); + tok->is_double = 0; + goto redo_char; + default: tok->err = json_tokener_error_parse_unexpected; goto out; + } + break; + + case json_tokener_state_finish: + if (tok->depth == 0) + goto out; + obj = json_object_get(current); + json_tokener_reset_level(tok, tok->depth); + tok->depth--; + goto redo_char; + + case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */ { - tok->err = json_tokener_error_parse_unexpected; - goto out; + /* If we were guaranteed to have len set, then we could (usually) handle + * the entire "Infinity" check in a single strncmp (strncasecmp), but + * since len might be -1 (i.e. "read until \0"), we need to check it + * a character at a time. + * Trying to handle it both ways would make this code considerably more + * complicated with likely little performance benefit. + */ + int is_negative = 0; + const char *_json_inf_str = json_inf_str; + if (!(tok->flags & JSON_TOKENER_STRICT)) + _json_inf_str = json_inf_str_lower; + + /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */ + while (tok->st_pos < (int)json_inf_str_len) + { + char inf_char = *str; + if (!(tok->flags & JSON_TOKENER_STRICT)) + inf_char = tolower((unsigned char)*str); + if (inf_char != _json_inf_str[tok->st_pos]) + { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + tok->st_pos++; + (void)ADVANCE_CHAR(str, tok); + if (!PEEK_CHAR(c, tok)) + { + /* out of input chars, for now at least */ + goto out; + } + } + /* We checked the full length of "Infinity", so create the object. + * When handling -Infinity, the number parsing code will have dropped + * the "-" into tok->pb for us, so check it now. + */ + if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-') + { + is_negative = 1; + } + current = json_object_new_double(is_negative ? -INFINITY : INFINITY); + if (current == NULL) + goto out; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; } - tok->st_pos++; - (void)ADVANCE_CHAR(str, tok); - if (!PEEK_CHAR(c, tok)) + break; + case json_tokener_state_null: /* aka starts with 'n' */ { - /* out of input chars, for now at least */ - goto out; + int size; + int size_nan; + printbuf_memappend_fast(tok->pb, &c, 1); + size = json_min(tok->st_pos + 1, json_null_str_len); + size_nan = json_min(tok->st_pos + 1, json_nan_str_len); + if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_null_str, tok->pb->buf, size) == 0) || + (strncmp(json_null_str, tok->pb->buf, size) == 0)) + { + if (tok->st_pos == json_null_str_len) + { + current = NULL; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } + else if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) || + (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)) + { + if (tok->st_pos == json_nan_str_len) + { + current = json_object_new_double(NAN); + if (current == NULL) + goto out; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } + else + { + tok->err = json_tokener_error_parse_null; + goto out; + } + tok->st_pos++; } - } - /* We checked the full length of "Infinity", so create the object. - * When handling -Infinity, the number parsing code will have dropped - * the "-" into tok->pb for us, so check it now. - */ - if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-') - { - is_negative = 1; - } - current = json_object_new_double(is_negative - ? -INFINITY : INFINITY); - if (current == NULL) - goto out; - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - - } - break; - case json_tokener_state_null: /* aka starts with 'n' */ - { - int size; - int size_nan; - printbuf_memappend_fast(tok->pb, &c, 1); - size = json_min(tok->st_pos+1, json_null_str_len); - size_nan = json_min(tok->st_pos+1, json_nan_str_len); - if((!(tok->flags & JSON_TOKENER_STRICT) && - strncasecmp(json_null_str, tok->pb->buf, size) == 0) - || (strncmp(json_null_str, tok->pb->buf, size) == 0) - ) { - if (tok->st_pos == json_null_str_len) { - current = NULL; - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - } - else if ((!(tok->flags & JSON_TOKENER_STRICT) && - strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) || - (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0) - ) - { - if (tok->st_pos == json_nan_str_len) + break; + + case json_tokener_state_comment_start: + if (c == '*') + { + state = json_tokener_state_comment; + } + else if (c == '/') + { + state = json_tokener_state_comment_eol; + } + else + { + tok->err = json_tokener_error_parse_comment; + goto out; + } + printbuf_memappend_fast(tok->pb, &c, 1); + break; + + case json_tokener_state_comment: { - current = json_object_new_double(NAN); - if (current == NULL) - goto out; - saved_state = json_tokener_state_finish; + /* Advance until we change state */ + const char *case_start = str; + while (c != '*') + { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + goto out; + } + } + printbuf_memappend_fast(tok->pb, case_start, 1 + str - case_start); + state = json_tokener_state_comment_end; + } + break; + + case json_tokener_state_comment_eol: + { + /* Advance until we change state */ + const char *case_start = str; + while (c != '\n') + { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + goto out; + } + } + printbuf_memappend_fast(tok->pb, case_start, str - case_start); + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); + state = json_tokener_state_eatws; + } + break; + + case json_tokener_state_comment_end: + printbuf_memappend_fast(tok->pb, &c, 1); + if (c == '/') + { + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); + state = json_tokener_state_eatws; + } + else + { + state = json_tokener_state_comment; + } + break; + + case json_tokener_state_string: + { + /* Advance until we change state */ + const char *case_start = str; + while (1) + { + if (c == tok->quote_char) + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + current = + json_object_new_string_len(tok->pb->buf, tok->pb->bpos); + if (current == NULL) + goto out; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + break; + } + else if (c == '\\') + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + saved_state = json_tokener_state_string; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + goto out; + } + } + } + break; + + case json_tokener_state_string_escape: + switch (c) + { + case '"': + case '\\': + case '/': + printbuf_memappend_fast(tok->pb, &c, 1); + state = saved_state; + break; + case 'b': + case 'n': + case 'r': + case 't': + case 'f': + if (c == 'b') + printbuf_memappend_fast(tok->pb, "\b", 1); + else if (c == 'n') + printbuf_memappend_fast(tok->pb, "\n", 1); + else if (c == 'r') + printbuf_memappend_fast(tok->pb, "\r", 1); + else if (c == 't') + printbuf_memappend_fast(tok->pb, "\t", 1); + else if (c == 'f') + printbuf_memappend_fast(tok->pb, "\f", 1); + state = saved_state; + break; + case 'u': + tok->ucs_char = 0; + tok->st_pos = 0; + state = json_tokener_state_escape_unicode; + break; + default: tok->err = json_tokener_error_parse_string; goto out; + } + break; + + // =================================================== + + case json_tokener_state_escape_unicode: + { + /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */ + while (1) + { + if (!c || !strchr(json_hex_chars, c)) + { + tok->err = json_tokener_error_parse_string; + goto out; + } + tok->ucs_char |= + ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4)); + tok->st_pos++; + if (tok->st_pos >= 4) + break; + + (void)ADVANCE_CHAR(str, tok); + if (!PEEK_CHAR(c, tok)) + { + /* + * We're out of characters in the current call to + * json_tokener_parse(), but a subsequent call might + * provide us with more, so leave our current state + * as-is (including tok->high_surrogate) and return. + */ + goto out; + } + } + tok->st_pos = 0; + + /* Now, we have a full \uNNNN sequence in tok->ucs_char */ + + /* If the *previous* sequence was a high surrogate ... */ + if (tok->high_surrogate) + { + if (IS_LOW_SURROGATE(tok->ucs_char)) + { + /* Recalculate the ucs_char, then fall thru to process normally */ + tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate, + tok->ucs_char); + } + else + { + /* High surrogate was not followed by a low surrogate + * Replace the high and process the rest normally + */ + printbuf_memappend_fast(tok->pb, + (char *)utf8_replacement_char, 3); + } + tok->high_surrogate = 0; + } + + if (tok->ucs_char < 0x80) + { + unsigned char unescaped_utf[1]; + unescaped_utf[0] = tok->ucs_char; + printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 1); + } + else if (tok->ucs_char < 0x800) + { + unsigned char unescaped_utf[2]; + unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6); + unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); + printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 2); + } + else if (IS_HIGH_SURROGATE(tok->ucs_char)) + { + /* + * The next two characters should be \u, HOWEVER, + * we can't simply peek ahead here, because the + * characters we need might not be passed to us + * until a subsequent call to json_tokener_parse. + * Instead, transition throug a couple of states. + * (now): + * _escape_unicode => _unicode_need_escape + * (see a '\\' char): + * _unicode_need_escape => _unicode_need_u + * (see a 'u' char): + * _unicode_need_u => _escape_unicode + * ...and we'll end up back around here. + */ + tok->high_surrogate = tok->ucs_char; + tok->ucs_char = 0; + state = json_tokener_state_escape_unicode_need_escape; + break; + } + else if (IS_LOW_SURROGATE(tok->ucs_char)) + { + /* Got a low surrogate not preceded by a high */ + printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); + } + else if (tok->ucs_char < 0x10000) + { + unsigned char unescaped_utf[3]; + unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12); + unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); + unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f); + printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 3); + } + else if (tok->ucs_char < 0x110000) + { + unsigned char unescaped_utf[4]; + unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07); + unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f); + unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); + unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f); + printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 4); + } + else + { + /* Don't know what we got--insert the replacement char */ + printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); + } + state = saved_state; // i.e. _state_string or _state_object_field + } + break; + + case json_tokener_state_escape_unicode_need_escape: + // We get here after processing a high_surrogate + // require a '\\' char + if (!c || c != '\\') + { + /* Got a high surrogate without another sequence following + * it. Put a replacement char in for the high surrogate + * and pop back up to _state_string or _state_object_field. + */ + printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); + tok->high_surrogate = 0; + tok->ucs_char = 0; + tok->st_pos = 0; + state = saved_state; + goto redo_char; + } + state = json_tokener_state_escape_unicode_need_u; + break; + + case json_tokener_state_escape_unicode_need_u: + /* We already had a \ char, check that it's \u */ + if (!c || c != 'u') + { + /* Got a high surrogate with some non-unicode escape + * sequence following it. + * Put a replacement char in for the high surrogate + * and handle the escape sequence normally. + */ + printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); + tok->high_surrogate = 0; + tok->ucs_char = 0; + tok->st_pos = 0; + state = json_tokener_state_string_escape; + goto redo_char; + } + state = json_tokener_state_escape_unicode; + break; + + // =================================================== + + case json_tokener_state_boolean: + { + int size1, size2; + printbuf_memappend_fast(tok->pb, &c, 1); + size1 = json_min(tok->st_pos + 1, json_true_str_len); + size2 = json_min(tok->st_pos + 1, json_false_str_len); + if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_true_str, tok->pb->buf, size1) == 0) || + (strncmp(json_true_str, tok->pb->buf, size1) == 0)) + { + if (tok->st_pos == json_true_str_len) + { + current = json_object_new_boolean(1); + if (current == NULL) + goto out; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } + else if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_false_str, tok->pb->buf, size2) == 0) || + (strncmp(json_false_str, tok->pb->buf, size2) == 0)) + { + if (tok->st_pos == json_false_str_len) + { + current = json_object_new_boolean(0); + if (current == NULL) + goto out; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } + else + { + tok->err = json_tokener_error_parse_boolean; + goto out; + } + tok->st_pos++; + } + break; + + case json_tokener_state_number: + { + /* Advance until we change state */ + const char *case_start = str; + int case_len = 0; + int is_exponent = 0; + int neg_sign_ok = 1; + int pos_sign_ok = 0; + if (printbuf_length(tok->pb) > 0) + { + /* We don't save all state from the previous incremental parse + so we need to re-generate it based on the saved string so far. + */ + char *e_loc = strchr(tok->pb->buf, 'e'); + if (!e_loc) + e_loc = strchr(tok->pb->buf, 'E'); + if (e_loc) + { + char *last_saved_char = + &tok->pb->buf[printbuf_length(tok->pb) - 1]; + is_exponent = 1; + pos_sign_ok = neg_sign_ok = 1; + /* If the "e" isn't at the end, we can't start with a '-' */ + if (e_loc != last_saved_char) + { + neg_sign_ok = 0; + pos_sign_ok = 0; + } + // else leave it set to 1, i.e. start of the new input + } + } + + while (c && ((c >= '0' && c <= '9') || + (!is_exponent && (c == 'e' || c == 'E')) || + (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') || + (!tok->is_double && c == '.'))) + { + pos_sign_ok = neg_sign_ok = 0; + ++case_len; + + /* non-digit characters checks */ + /* note: since the main loop condition to get here was + * an input starting with 0-9 or '-', we are + * protected from input starting with '.' or + * e/E. + */ + switch (c) + { + case '.': + tok->is_double = 1; + pos_sign_ok = 1; + neg_sign_ok = 1; + break; + case 'e': /* FALLTHRU */ + case 'E': + is_exponent = 1; + tok->is_double = 1; + /* the exponent part can begin with a negative sign */ + pos_sign_ok = neg_sign_ok = 1; + break; + default: break; + } + + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { + printbuf_memappend_fast(tok->pb, case_start, case_len); + goto out; + } + } + /* + Now we know c isn't a valid number char, but check whether + it might have been intended to be, and return a potentially + more understandable error right away. + However, if we're at the top-level, use the number as-is + because c can be part of a new object to parse on the + next call to json_tokener_parse(). + */ + if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' && + c != 'I' && c != 'i' && !isspace((unsigned char)c)) + { + tok->err = json_tokener_error_parse_number; + goto out; + } + if (case_len > 0) + printbuf_memappend_fast(tok->pb, case_start, case_len); + + // Check for -Infinity + if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I')) + { + state = json_tokener_state_inf; + tok->st_pos = 0; + goto redo_char; + } + if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT)) + { + /* Trim some chars off the end, to allow things + like "123e+" to parse ok. */ + while (printbuf_length(tok->pb) > 1) + { + char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1]; + if (last_char != 'e' && last_char != 'E' && + last_char != '-' && last_char != '+') + { + break; + } + tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0'; + printbuf_length(tok->pb)--; + } + } + } + { + int64_t num64; + uint64_t numuint64; + double numd; + if (!tok->is_double && tok->pb->buf[0] == '-' && + json_parse_int64(tok->pb->buf, &num64) == 0) + { + current = json_object_new_int64(num64); + if (current == NULL) + goto out; + } + else if (!tok->is_double && tok->pb->buf[0] != '-' && + json_parse_uint64(tok->pb->buf, &numuint64) == 0) + { + if (numuint64 && tok->pb->buf[0] == '0' && + (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_number; + goto out; + } + if (numuint64 <= INT64_MAX) + { + num64 = (uint64_t)numuint64; + current = json_object_new_int64(num64); + if (current == NULL) + goto out; + } + else + { + current = json_object_new_uint64(numuint64); + if (current == NULL) + goto out; + } + } + else if (tok->is_double && + json_tokener_parse_double( + tok->pb->buf, printbuf_length(tok->pb), &numd) == 0) + { + current = json_object_new_double_s(numd, tok->pb->buf); + if (current == NULL) + goto out; + } + else + { + tok->err = json_tokener_error_parse_number; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + break; + + case json_tokener_state_array_after_sep: + case json_tokener_state_array: + if (c == ']') + { + // Minimize memory usage; assume parsed objs are unlikely to be changed + json_object_array_shrink(current, 0); + + if (state == json_tokener_state_array_after_sep && + (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } + else + { + if (tok->depth >= tok->max_depth - 1) + { + tok->err = json_tokener_error_depth; + goto out; + } + state = json_tokener_state_array_add; + tok->depth++; + json_tokener_reset_level(tok, tok->depth); + goto redo_char; + } + break; + + case json_tokener_state_array_add: + if (json_object_array_add(current, obj) != 0) + goto out; + saved_state = json_tokener_state_array_sep; state = json_tokener_state_eatws; goto redo_char; + + case json_tokener_state_array_sep: + if (c == ']') + { + // Minimize memory usage; assume parsed objs are unlikely to be changed + json_object_array_shrink(current, 0); + + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } + else if (c == ',') + { + saved_state = json_tokener_state_array_after_sep; + state = json_tokener_state_eatws; + } + else + { + tok->err = json_tokener_error_parse_array; + goto out; + } + break; + + case json_tokener_state_object_field_start: + case json_tokener_state_object_field_start_after_sep: + if (c == '}') + { + if (state == json_tokener_state_object_field_start_after_sep && + (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } + else if (c == '"' || c == '\'') + { + tok->quote_char = c; + printbuf_reset(tok->pb); + state = json_tokener_state_object_field; + } + else + { + tok->err = json_tokener_error_parse_object_key_name; + goto out; + } + break; + + case json_tokener_state_object_field: + { + /* Advance until we change state */ + const char *case_start = str; + while (1) + { + if (c == tok->quote_char) + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + obj_field_name = strdup(tok->pb->buf); + saved_state = json_tokener_state_object_field_end; + state = json_tokener_state_eatws; + break; + } + else if (c == '\\') + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + saved_state = json_tokener_state_object_field; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { + printbuf_memappend_fast(tok->pb, case_start, + str - case_start); + goto out; + } + } } - } else { - tok->err = json_tokener_error_parse_null; - goto out; - } - tok->st_pos++; - } - break; - - case json_tokener_state_comment_start: - if(c == '*') { - state = json_tokener_state_comment; - } else if(c == '/') { - state = json_tokener_state_comment_eol; - } else { - tok->err = json_tokener_error_parse_comment; - goto out; - } - printbuf_memappend_fast(tok->pb, &c, 1); - break; - - case json_tokener_state_comment: - { - /* Advance until we change state */ - const char *case_start = str; - while(c != '*') { - if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start); - state = json_tokener_state_comment_end; - } - break; - - case json_tokener_state_comment_eol: - { - /* Advance until we change state */ - const char *case_start = str; - while(c != '\n') { - if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); - state = json_tokener_state_eatws; - } - break; - - case json_tokener_state_comment_end: - printbuf_memappend_fast(tok->pb, &c, 1); - if(c == '/') { - MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); - state = json_tokener_state_eatws; - } else { - state = json_tokener_state_comment; - } - break; - - case json_tokener_state_string: - { - /* Advance until we change state */ - const char *case_start = str; - while(1) { - if(c == tok->quote_char) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos); - if(current == NULL) - goto out; - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - break; - } else if(c == '\\') { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - saved_state = json_tokener_state_string; - state = json_tokener_state_string_escape; - break; - } - if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - } - break; - - case json_tokener_state_string_escape: - switch(c) { - case '"': - case '\\': - case '/': - printbuf_memappend_fast(tok->pb, &c, 1); - state = saved_state; - break; - case 'b': - case 'n': - case 'r': - case 't': - case 'f': - if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1); - else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1); - else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1); - else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1); - else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1); - state = saved_state; - break; - case 'u': - tok->ucs_char = 0; - tok->st_pos = 0; - state = json_tokener_state_escape_unicode; - break; - default: - tok->err = json_tokener_error_parse_string; - goto out; - } - break; - - case json_tokener_state_escape_unicode: - { - unsigned int got_hi_surrogate = 0; - - /* Handle a 4-byte sequence, or two sequences if a surrogate pair */ - while(1) { - if (c && strchr(json_hex_chars, c)) { - tok->ucs_char += ((unsigned int)jt_hexdigit(c) << ((3-tok->st_pos++)*4)); - if(tok->st_pos == 4) { - unsigned char unescaped_utf[4]; - - if (got_hi_surrogate) { - if (IS_LOW_SURROGATE(tok->ucs_char)) { - /* Recalculate the ucs_char, then fall thru to process normally */ - tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char); - } else { - /* Hi surrogate was not followed by a low surrogate */ - /* Replace the hi and process the rest normally */ - printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); - } - got_hi_surrogate = 0; - } - - if (tok->ucs_char < 0x80) { - unescaped_utf[0] = tok->ucs_char; - printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1); - } else if (tok->ucs_char < 0x800) { - unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6); - unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); - printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2); - } else if (IS_HIGH_SURROGATE(tok->ucs_char)) { - /* Got a high surrogate. Remember it and look for the - * the beginning of another sequence, which should be the - * low surrogate. - */ - got_hi_surrogate = tok->ucs_char; - /* Not at end, and the next two chars should be "\u" */ - if ((len == -1 || len > (tok->char_offset + 2)) && - // str[0] != '0' && // implied by json_hex_chars, above. - (str[1] == '\\') && - (str[2] == 'u')) - { - /* Advance through the 16 bit surrogate, and move on to the - * next sequence. The next step is to process the following - * characters. - */ - if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) { - printbuf_memappend_fast(tok->pb, - (char*) utf8_replacement_char, 3); - } - /* Advance to the first char of the next sequence and - * continue processing with the next sequence. - */ - if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, - (char*) utf8_replacement_char, 3); - goto out; - } - tok->ucs_char = 0; - tok->st_pos = 0; - continue; /* other json_tokener_state_escape_unicode */ - } else { - /* Got a high surrogate without another sequence following - * it. Put a replacement char in for the hi surrogate - * and pretend we finished. - */ - printbuf_memappend_fast(tok->pb, - (char*) utf8_replacement_char, 3); - } - } else if (IS_LOW_SURROGATE(tok->ucs_char)) { - /* Got a low surrogate not preceded by a high */ - printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); - } else if (tok->ucs_char < 0x10000) { - unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12); - unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); - unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f); - printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3); - } else if (tok->ucs_char < 0x110000) { - unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07); - unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f); - unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); - unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f); - printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4); - } else { - /* Don't know what we got--insert the replacement char */ - printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); - } - state = saved_state; break; - } - } else { - tok->err = json_tokener_error_parse_string; - goto out; - } - if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { - if (got_hi_surrogate) /* Clean up any pending chars */ - printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); - goto out; - } - } - } - break; - - case json_tokener_state_boolean: - { - int size1, size2; - printbuf_memappend_fast(tok->pb, &c, 1); - size1 = json_min(tok->st_pos+1, json_true_str_len); - size2 = json_min(tok->st_pos+1, json_false_str_len); - if((!(tok->flags & JSON_TOKENER_STRICT) && - strncasecmp(json_true_str, tok->pb->buf, size1) == 0) - || (strncmp(json_true_str, tok->pb->buf, size1) == 0) - ) { - if(tok->st_pos == json_true_str_len) { - current = json_object_new_boolean(1); - if(current == NULL) - goto out; - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - } else if((!(tok->flags & JSON_TOKENER_STRICT) && - strncasecmp(json_false_str, tok->pb->buf, size2) == 0) - || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) { - if(tok->st_pos == json_false_str_len) { - current = json_object_new_boolean(0); - if(current == NULL) - goto out; - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - } else { - tok->err = json_tokener_error_parse_boolean; - goto out; - } - tok->st_pos++; - } - break; - - case json_tokener_state_number: - { - /* Advance until we change state */ - const char *case_start = str; - int case_len=0; - int is_exponent=0; - int negativesign_next_possible_location=1; - while(c && strchr(json_number_chars, c)) { - ++case_len; - - /* non-digit characters checks */ - /* note: since the main loop condition to get here was - an input starting with 0-9 or '-', we are - protected from input starting with '.' or - e/E. */ - if (c == '.') { - if (tok->is_double != 0) { - /* '.' can only be found once, and out of the exponent part. - Thus, if the input is already flagged as double, it - is invalid. */ - tok->err = json_tokener_error_parse_number; - goto out; - } - tok->is_double = 1; - } - if (c == 'e' || c == 'E') { - if (is_exponent != 0) { - /* only one exponent possible */ - tok->err = json_tokener_error_parse_number; - goto out; - } - is_exponent = 1; - tok->is_double = 1; - /* the exponent part can begin with a negative sign */ - negativesign_next_possible_location = case_len + 1; - } - if (c == '-' && case_len != negativesign_next_possible_location) { - /* If the negative sign is not where expected (ie - start of input or start of exponent part), the - input is invalid. */ - tok->err = json_tokener_error_parse_number; - goto out; - } - - if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, case_len); - goto out; - } - } - if (case_len>0) - printbuf_memappend_fast(tok->pb, case_start, case_len); - - // Check for -Infinity - if (tok->pb->buf[0] == '-' && case_len <= 1 && - (c == 'i' || c == 'I')) - { - state = json_tokener_state_inf; - tok->st_pos = 0; - goto redo_char; - } - } - { - int64_t num64; - double numd; - if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { - if (num64 && tok->pb->buf[0]=='0' && - (tok->flags & JSON_TOKENER_STRICT)) { - /* in strict mode, number must not start with 0 */ - tok->err = json_tokener_error_parse_number; - goto out; - } - current = json_object_new_int64(num64); - if(current == NULL) - goto out; - } - else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) - { - current = json_object_new_double_s(numd, tok->pb->buf); - if(current == NULL) - goto out; - } else { - tok->err = json_tokener_error_parse_number; - goto out; - } - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - break; - - case json_tokener_state_array_after_sep: - case json_tokener_state_array: - if(c == ']') { - if (state == json_tokener_state_array_after_sep && - (tok->flags & JSON_TOKENER_STRICT)) - { - tok->err = json_tokener_error_parse_unexpected; - goto out; - } - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else { - if(tok->depth >= tok->max_depth-1) { - tok->err = json_tokener_error_depth; - goto out; - } - state = json_tokener_state_array_add; - tok->depth++; - json_tokener_reset_level(tok, tok->depth); - goto redo_char; - } - break; - - case json_tokener_state_array_add: - if( json_object_array_add(current, obj) != 0 ) - goto out; - saved_state = json_tokener_state_array_sep; - state = json_tokener_state_eatws; - goto redo_char; - - case json_tokener_state_array_sep: - if(c == ']') { - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else if(c == ',') { - saved_state = json_tokener_state_array_after_sep; - state = json_tokener_state_eatws; - } else { - tok->err = json_tokener_error_parse_array; - goto out; - } - break; - - case json_tokener_state_object_field_start: - case json_tokener_state_object_field_start_after_sep: - if(c == '}') { - if (state == json_tokener_state_object_field_start_after_sep && - (tok->flags & JSON_TOKENER_STRICT)) - { - tok->err = json_tokener_error_parse_unexpected; - goto out; - } - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else if (c == '"' || c == '\'') { - tok->quote_char = c; - printbuf_reset(tok->pb); - state = json_tokener_state_object_field; - } else { - tok->err = json_tokener_error_parse_object_key_name; - goto out; - } - break; - - case json_tokener_state_object_field: - { - /* Advance until we change state */ - const char *case_start = str; - while(1) { - if(c == tok->quote_char) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - obj_field_name = strdup(tok->pb->buf); - saved_state = json_tokener_state_object_field_end; - state = json_tokener_state_eatws; - break; - } else if(c == '\\') { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - saved_state = json_tokener_state_object_field; - state = json_tokener_state_string_escape; - break; - } - if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - } - break; - - case json_tokener_state_object_field_end: - if(c == ':') { - saved_state = json_tokener_state_object_value; - state = json_tokener_state_eatws; - } else { - tok->err = json_tokener_error_parse_object_key_sep; - goto out; - } - break; - - case json_tokener_state_object_value: - if(tok->depth >= tok->max_depth-1) { - tok->err = json_tokener_error_depth; - goto out; - } - state = json_tokener_state_object_value_add; - tok->depth++; - json_tokener_reset_level(tok, tok->depth); - goto redo_char; - - case json_tokener_state_object_value_add: - json_object_object_add(current, obj_field_name, obj); - free(obj_field_name); - obj_field_name = NULL; - saved_state = json_tokener_state_object_sep; - state = json_tokener_state_eatws; - goto redo_char; - - case json_tokener_state_object_sep: - /* { */ - if(c == '}') { - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else if(c == ',') { - saved_state = json_tokener_state_object_field_start_after_sep; - state = json_tokener_state_eatws; - } else { - tok->err = json_tokener_error_parse_object_value_sep; - goto out; - } - break; - - } - if (!ADVANCE_CHAR(str, tok)) - goto out; - } /* while(PEEK_CHAR) */ - - out: - if (c && - (state == json_tokener_state_finish) && - (tok->depth == 0) && - (tok->flags & JSON_TOKENER_STRICT)) { - /* unexpected char after JSON data */ - tok->err = json_tokener_error_parse_unexpected; - } - if (!c) { /* We hit an eof char (0) */ - if(state != json_tokener_state_finish && - saved_state != json_tokener_state_finish) - tok->err = json_tokener_error_parse_eof; - } + + case json_tokener_state_object_field_end: + if (c == ':') + { + saved_state = json_tokener_state_object_value; + state = json_tokener_state_eatws; + } + else + { + tok->err = json_tokener_error_parse_object_key_sep; + goto out; + } + break; + + case json_tokener_state_object_value: + if (tok->depth >= tok->max_depth - 1) + { + tok->err = json_tokener_error_depth; + goto out; + } + state = json_tokener_state_object_value_add; + tok->depth++; + json_tokener_reset_level(tok, tok->depth); + goto redo_char; + + case json_tokener_state_object_value_add: + json_object_object_add(current, obj_field_name, obj); + free(obj_field_name); + obj_field_name = NULL; + saved_state = json_tokener_state_object_sep; + state = json_tokener_state_eatws; + goto redo_char; + + case json_tokener_state_object_sep: + /* { */ + if (c == '}') + { + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } + else if (c == ',') + { + saved_state = json_tokener_state_object_field_start_after_sep; + state = json_tokener_state_eatws; + } + else + { + tok->err = json_tokener_error_parse_object_value_sep; + goto out; + } + break; + } + (void)ADVANCE_CHAR(str, tok); + if (!c) // This is the char *before* advancing + break; + } /* while(PEEK_CHAR) */ + +out: + if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0)) + { + tok->err = json_tokener_error_parse_utf8_string; + } + if (c && (state == json_tokener_state_finish) && (tok->depth == 0) && + (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) == + JSON_TOKENER_STRICT) + { + /* unexpected char after JSON data */ + tok->err = json_tokener_error_parse_unexpected; + } + if (!c) + { + /* We hit an eof char (0) */ + if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish) + tok->err = json_tokener_error_parse_eof; + } #ifdef HAVE_USELOCALE - uselocale(oldlocale); - freelocale(newloc); + uselocale(oldlocale); + freelocale(newloc); #elif defined(HAVE_SETLOCALE) - setlocale(LC_NUMERIC, oldlocale); - free(oldlocale); + setlocale(LC_NUMERIC, oldlocale); + free(oldlocale); #endif - if (tok->err == json_tokener_success) - { - json_object *ret = json_object_get(current); - int ii; - - /* Partially reset, so we parse additional objects on subsequent calls. */ - for(ii = tok->depth; ii >= 0; ii--) - json_tokener_reset_level(tok, ii); - return ret; - } - - MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", - json_tokener_errors[tok->err], tok->char_offset); - return NULL; + if (tok->err == json_tokener_success) + { + json_object *ret = json_object_get(current); + int ii; + + /* Partially reset, so we parse additional objects on subsequent calls. */ + for (ii = tok->depth; ii >= 0; ii--) + json_tokener_reset_level(tok, ii); + return ret; + } + + MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err], + tok->char_offset); + return NULL; +} + +static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes) +{ + unsigned char chr = c; + if (*nBytes == 0) + { + if (chr >= 0x80) + { + if ((chr & 0xe0) == 0xc0) + *nBytes = 1; + else if ((chr & 0xf0) == 0xe0) + *nBytes = 2; + else if ((chr & 0xf8) == 0xf0) + *nBytes = 3; + else + return 0; + } + } + else + { + if ((chr & 0xC0) != 0x80) + return 0; + (*nBytes)--; + } + return 1; } void json_tokener_set_flags(struct json_tokener *tok, int flags) { tok->flags = flags; } + +size_t json_tokener_get_parse_end(struct json_tokener *tok) +{ + assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */ + return (size_t)tok->char_offset; +} + +static int json_tokener_parse_double(const char *buf, int len, double *retval) +{ + char *end; + *retval = strtod(buf, &end); + if (buf + len == end) + return 0; // It worked + return 1; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_tokener.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_tokener.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_tokener.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_tokener.h 2022-04-15 07:49:22.000000000 +0000 @@ -16,80 +16,125 @@ #ifndef _json_tokener_h_ #define _json_tokener_h_ -#include #include "json_object.h" +#include #ifdef __cplusplus extern "C" { #endif -enum json_tokener_error { - json_tokener_success, - json_tokener_continue, - json_tokener_error_depth, - json_tokener_error_parse_eof, - json_tokener_error_parse_unexpected, - json_tokener_error_parse_null, - json_tokener_error_parse_boolean, - json_tokener_error_parse_number, - json_tokener_error_parse_array, - json_tokener_error_parse_object_key_name, - json_tokener_error_parse_object_key_sep, - json_tokener_error_parse_object_value_sep, - json_tokener_error_parse_string, - json_tokener_error_parse_comment, - json_tokener_error_size +enum json_tokener_error +{ + json_tokener_success, + json_tokener_continue, + json_tokener_error_depth, + json_tokener_error_parse_eof, + json_tokener_error_parse_unexpected, + json_tokener_error_parse_null, + json_tokener_error_parse_boolean, + json_tokener_error_parse_number, + json_tokener_error_parse_array, + json_tokener_error_parse_object_key_name, + json_tokener_error_parse_object_key_sep, + json_tokener_error_parse_object_value_sep, + json_tokener_error_parse_string, + json_tokener_error_parse_comment, + json_tokener_error_parse_utf8_string, + json_tokener_error_size }; -enum json_tokener_state { - json_tokener_state_eatws, - json_tokener_state_start, - json_tokener_state_finish, - json_tokener_state_null, - json_tokener_state_comment_start, - json_tokener_state_comment, - json_tokener_state_comment_eol, - json_tokener_state_comment_end, - json_tokener_state_string, - json_tokener_state_string_escape, - json_tokener_state_escape_unicode, - json_tokener_state_boolean, - json_tokener_state_number, - json_tokener_state_array, - json_tokener_state_array_add, - json_tokener_state_array_sep, - json_tokener_state_object_field_start, - json_tokener_state_object_field, - json_tokener_state_object_field_end, - json_tokener_state_object_value, - json_tokener_state_object_value_add, - json_tokener_state_object_sep, - json_tokener_state_array_after_sep, - json_tokener_state_object_field_start_after_sep, - json_tokener_state_inf +/** + * @deprecated Don't use this outside of json_tokener.c, it will be made private in a future release. + */ +enum json_tokener_state +{ + json_tokener_state_eatws, + json_tokener_state_start, + json_tokener_state_finish, + json_tokener_state_null, + json_tokener_state_comment_start, + json_tokener_state_comment, + json_tokener_state_comment_eol, + json_tokener_state_comment_end, + json_tokener_state_string, + json_tokener_state_string_escape, + json_tokener_state_escape_unicode, + json_tokener_state_escape_unicode_need_escape, + json_tokener_state_escape_unicode_need_u, + json_tokener_state_boolean, + json_tokener_state_number, + json_tokener_state_array, + json_tokener_state_array_add, + json_tokener_state_array_sep, + json_tokener_state_object_field_start, + json_tokener_state_object_field, + json_tokener_state_object_field_end, + json_tokener_state_object_value, + json_tokener_state_object_value_add, + json_tokener_state_object_sep, + json_tokener_state_array_after_sep, + json_tokener_state_object_field_start_after_sep, + json_tokener_state_inf }; +/** + * @deprecated Don't use this outside of json_tokener.c, it will be made private in a future release. + */ struct json_tokener_srec { - enum json_tokener_state state, saved_state; - struct json_object *obj; - struct json_object *current; - char *obj_field_name; + enum json_tokener_state state, saved_state; + struct json_object *obj; + struct json_object *current; + char *obj_field_name; }; #define JSON_TOKENER_DEFAULT_DEPTH 32 +/** + * Internal state of the json parser. + * Do not access any fields of this structure directly. + * Its definition is published due to historical limitations + * in the json tokener API, and will be changed to be an opaque + * type in the future. + */ struct json_tokener { - char *str; - struct printbuf *pb; - int max_depth, depth, is_double, st_pos, char_offset; - enum json_tokener_error err; - unsigned int ucs_char; - char quote_char; - struct json_tokener_srec *stack; - int flags; + /** + * @deprecated Do not access any of these fields outside of json_tokener.c + */ + char *str; + struct printbuf *pb; + int max_depth, depth, is_double, st_pos; + /** + * @deprecated See json_tokener_get_parse_end() instead. + */ + int char_offset; + /** + * @deprecated See json_tokener_get_error() instead. + */ + enum json_tokener_error err; + unsigned int ucs_char, high_surrogate; + char quote_char; + struct json_tokener_srec *stack; + int flags; }; + +/** + * Return the offset of the byte after the last byte parsed + * relative to the start of the most recent string passed in + * to json_tokener_parse_ex(). i.e. this is where parsing + * would start again if the input contains another JSON object + * after the currently parsed one. + * + * Note that when multiple parse calls are issued, this is *not* the + * total number of characters parsed. + * + * In the past this would have been accessed as tok->char_offset. + * + * See json_tokener_parse_ex() for an example of how to use this. + */ +JSON_EXPORT size_t json_tokener_get_parse_end(struct json_tokener *tok); + /** * @deprecated Unused in json-c code */ @@ -101,11 +146,36 @@ * restrictive from one release to the next, causing your * code to fail on previously working input. * + * Note that setting this will also effectively disable parsing + * of multiple json objects in a single character stream + * (e.g. {"foo":123}{"bar":234}); if you want to allow that + * also set JSON_TOKENER_ALLOW_TRAILING_CHARS + * + * This flag is not set by default. + * + * @see json_tokener_set_flags() + */ +#define JSON_TOKENER_STRICT 0x01 + +/** + * Use with JSON_TOKENER_STRICT to allow trailing characters after the + * first parsed object. + * + * @see json_tokener_set_flags() + */ +#define JSON_TOKENER_ALLOW_TRAILING_CHARS 0x02 + +/** + * Cause json_tokener_parse_ex() to validate that input is UTF8. + * If this flag is specified and validation fails, then + * json_tokener_get_error(tok) will return + * json_tokener_error_parse_utf8_string + * * This flag is not set by default. * * @see json_tokener_set_flags() */ -#define JSON_TOKENER_STRICT 0x01 +#define JSON_TOKENER_VALIDATE_UTF8 0x10 /** * Given an error previously returned by json_tokener_get_error(), @@ -113,7 +183,7 @@ * * @return a generic error message is returned if an invalid error value is provided. */ -const char *json_tokener_error_desc(enum json_tokener_error jerr); +JSON_EXPORT const char *json_tokener_error_desc(enum json_tokener_error jerr); /** * Retrieve the error caused by the last call to json_tokener_parse_ex(), @@ -122,16 +192,50 @@ * When parsing a JSON string in pieces, if the tokener is in the middle * of parsing this will return json_tokener_continue. * - * See also json_tokener_error_desc(). + * @see json_tokener_error_desc(). */ JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok); -JSON_EXPORT struct json_tokener* json_tokener_new(void); -JSON_EXPORT struct json_tokener* json_tokener_new_ex(int depth); +/** + * Allocate a new json_tokener. + * When done using that to parse objects, free it with json_tokener_free(). + * See json_tokener_parse_ex() for usage details. + */ +JSON_EXPORT struct json_tokener *json_tokener_new(void); + +/** + * Allocate a new json_tokener with a custom max nesting depth. + * @see JSON_TOKENER_DEFAULT_DEPTH + */ +JSON_EXPORT struct json_tokener *json_tokener_new_ex(int depth); + +/** + * Free a json_tokener previously allocated with json_tokener_new(). + */ JSON_EXPORT void json_tokener_free(struct json_tokener *tok); + +/** + * Reset the state of a json_tokener, to prepare to parse a + * brand new JSON object. + */ JSON_EXPORT void json_tokener_reset(struct json_tokener *tok); -JSON_EXPORT struct json_object* json_tokener_parse(const char *str); -JSON_EXPORT struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error); + +/** + * Parse a json_object out of the string `str`. + * + * If you need more control over how the parsing occurs, + * see json_tokener_parse_ex(). + */ +JSON_EXPORT struct json_object *json_tokener_parse(const char *str); + +/** + * Parser a json_object out of the string `str`, but if it fails + * return the error in `*error`. + * @see json_tokener_parse() + * @see json_tokener_parse_ex() + */ +JSON_EXPORT struct json_object *json_tokener_parse_verbose(const char *str, + enum json_tokener_error *error); /** * Set flags that control how parsing will be done. @@ -151,26 +255,32 @@ * * If json_tokener_parse_ex() returns NULL and the error is anything other than * json_tokener_continue, a fatal error has occurred and parsing must be - * halted. Then, the tok object must not be reused until json_tokener_reset() is - * called. + * halted. Then, the tok object must not be reused until json_tokener_reset() + * is called. * * When a valid JSON value is parsed, a non-NULL json_object will be - * returned. Also, json_tokener_get_error() will return json_tokener_success. - * Be sure to check the type with json_object_is_type() or - * json_object_get_type() before using the object. + * returned, with a reference count of one which belongs to the caller. Also, + * json_tokener_get_error() will return json_tokener_success. Be sure to check + * the type with json_object_is_type() or json_object_get_type() before using + * the object. * - * @b XXX this shouldn't use internal fields: * Trailing characters after the parsed value do not automatically cause an * error. It is up to the caller to decide whether to treat this as an * error or to handle the additional characters, perhaps by parsing another * json value starting from that point. * - * Extra characters can be detected by comparing the tok->char_offset against + * If the caller knows that they are at the end of their input, the length + * passed MUST include the final '\0' character, so values with no inherent + * end (i.e. numbers) can be properly parsed, rather than just returning + * json_tokener_continue. + * + * Extra characters can be detected by comparing the value returned by + * json_tokener_get_parse_end() against * the length of the last len parameter passed in. * * The tokener does \b not maintain an internal buffer so the caller is - * responsible for calling json_tokener_parse_ex with an appropriate str - * parameter starting with the extra characters. + * responsible for a subsequent call to json_tokener_parse_ex with an + * appropriate str parameter starting with the extra characters. * * This interface is presently not 64-bit clean due to the int len argument * so the function limits the maximum string size to INT32_MAX (2GB). @@ -186,6 +296,8 @@ do { mystring = ... // get JSON string, e.g. read from file, etc... stringlen = strlen(mystring); + if (end_of_input) + stringlen++; // Include the '\0' if we know we're at the end of input jobj = json_tokener_parse_ex(tok, mystring, stringlen); } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); if (jerr != json_tokener_success) @@ -193,7 +305,7 @@ fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); // Handle errors, as appropriate for your application. } -if (tok->char_offset < stringlen) // XXX shouldn't access internal fields +if (json_tokener_get_parse_end(tok) < stringlen) { // Handle extra characters after parsed object as desired. // e.g. issue an error, parse another object from that point, etc... @@ -206,8 +318,8 @@ * @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated. * @param len the length of str */ -JSON_EXPORT struct json_object* json_tokener_parse_ex(struct json_tokener *tok, - const char *str, int len); +JSON_EXPORT struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, + int len); #ifdef __cplusplus } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_types.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_types.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_types.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_types.h 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 Eric Hawicz + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + */ + +#ifndef _json_types_h_ +#define _json_types_h_ + +/** + * @file + * @brief Basic types used in a few places in json-c, but you should include "json_object.h" instead. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JSON_EXPORT +#if defined(_MSC_VER) +#define JSON_EXPORT __declspec(dllexport) +#else +#define JSON_EXPORT extern +#endif +#endif + +struct printbuf; + +/** + * A structure to use with json_object_object_foreachC() loops. + * Contains key, val and entry members. + */ +struct json_object_iter +{ + char *key; + struct json_object *val; + struct lh_entry *entry; +}; +typedef struct json_object_iter json_object_iter; + +typedef int json_bool; + +/** + * @brief The core type for all type of JSON objects handled by json-c + */ +typedef struct json_object json_object; + +/** + * Type of custom user delete functions. See json_object_set_serializer. + */ +typedef void(json_object_delete_fn)(struct json_object *jso, void *userdata); + +/** + * Type of a custom serialization function. See json_object_set_serializer. + */ +typedef int(json_object_to_json_string_fn)(struct json_object *jso, struct printbuf *pb, int level, + int flags); + +/* supported object types */ + +typedef enum json_type +{ + /* If you change this, be sure to update json_type_to_name() too */ + json_type_null, + json_type_boolean, + json_type_double, + json_type_int, + json_type_object, + json_type_array, + json_type_string +} json_type; + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_util.c thunderbird-91.8.1+build1/comm/third_party/json-c/json_util.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_util.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_util.c 2022-04-15 07:49:21.000000000 +0000 @@ -14,13 +14,13 @@ #include "strerror_override.h" +#include +#include #include +#include #include #include -#include -#include #include -#include #ifdef HAVE_SYS_TYPES_H #include @@ -35,31 +35,27 @@ #endif /* HAVE_FCNTL_H */ #ifdef HAVE_UNISTD_H -# include +#include #endif /* HAVE_UNISTD_H */ #ifdef WIN32 -# if MSC_VER < 1800 -/* strtoll is available only since Visual Studio 2013 */ -# define strtoll _strtoi64 -# endif -# define WIN32_LEAN_AND_MEAN -# include -# include +#define WIN32_LEAN_AND_MEAN +#include +#include #endif /* defined(WIN32) */ #if !defined(HAVE_OPEN) && defined(WIN32) -# define open _open +#define open _open #endif #include "snprintf_compat.h" #include "debug.h" -#include "printbuf.h" #include "json_inttypes.h" #include "json_object.h" #include "json_tokener.h" #include "json_util.h" +#include "printbuf.h" static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename); @@ -81,43 +77,74 @@ va_end(ap); } -struct json_object* json_object_from_fd(int fd) +struct json_object *json_object_from_fd(int fd) { - struct printbuf *pb; - struct json_object *obj; - char buf[JSON_FILE_BUF_SIZE]; - int ret; - - if(!(pb = printbuf_new())) { - _json_c_set_last_err("json_object_from_file: printbuf_new failed\n"); - return NULL; - } - while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) { - printbuf_memappend(pb, buf, ret); - } - if(ret < 0) { - _json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno)); - printbuf_free(pb); - return NULL; - } - obj = json_tokener_parse(pb->buf); - printbuf_free(pb); - return obj; -} - -struct json_object* json_object_from_file(const char *filename) -{ - struct json_object *obj; - int fd; - - if((fd = open(filename, O_RDONLY)) < 0) { - _json_c_set_last_err("json_object_from_file: error opening file %s: %s\n", - filename, strerror(errno)); - return NULL; - } - obj = json_object_from_fd(fd); - close(fd); - return obj; + return json_object_from_fd_ex(fd, -1); +} +struct json_object *json_object_from_fd_ex(int fd, int in_depth) +{ + struct printbuf *pb; + struct json_object *obj; + char buf[JSON_FILE_BUF_SIZE]; + int ret; + int depth = JSON_TOKENER_DEFAULT_DEPTH; + json_tokener *tok; + + if (!(pb = printbuf_new())) + { + _json_c_set_last_err("json_object_from_file: printbuf_new failed\n"); + return NULL; + } + + if (in_depth != -1) + depth = in_depth; + tok = json_tokener_new_ex(depth); + if (!tok) + { + _json_c_set_last_err( + "json_object_from_fd: unable to allocate json_tokener(depth=%d): %s\n", depth, + strerror(errno)); + printbuf_free(pb); + return NULL; + } + + while ((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) + { + printbuf_memappend(pb, buf, ret); + } + if (ret < 0) + { + _json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, + strerror(errno)); + json_tokener_free(tok); + printbuf_free(pb); + return NULL; + } + + obj = json_tokener_parse_ex(tok, pb->buf, printbuf_length(pb)); + if (obj == NULL) + _json_c_set_last_err("json_tokener_parse_ex failed: %s\n", + json_tokener_error_desc(json_tokener_get_error(tok))); + + json_tokener_free(tok); + printbuf_free(pb); + return obj; +} + +struct json_object *json_object_from_file(const char *filename) +{ + struct json_object *obj; + int fd; + + if ((fd = open(filename, O_RDONLY)) < 0) + { + _json_c_set_last_err("json_object_from_file: error opening file %s: %s\n", filename, + strerror(errno)); + return NULL; + } + obj = json_object_from_fd(fd); + close(fd); + return obj; } /* extended "format and write to file" function */ @@ -127,14 +154,16 @@ int fd, ret; int saved_errno; - if (!obj) { + if (!obj) + { _json_c_set_last_err("json_object_to_file: object is null\n"); return -1; } - if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { - _json_c_set_last_err("json_object_to_file: error opening file %s: %s\n", - filename, strerror(errno)); + if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) + { + _json_c_set_last_err("json_object_to_file: error opening file %s: %s\n", filename, + strerror(errno)); return -1; } ret = _json_object_to_fd(fd, obj, flags, filename); @@ -146,7 +175,8 @@ int json_object_to_fd(int fd, struct json_object *obj, int flags) { - if (!obj) { + if (!obj) + { _json_c_set_last_err("json_object_to_fd: object is null\n"); return -1; } @@ -161,17 +191,21 @@ filename = filename ? filename : "(fd)"; - if (!(json_str = json_object_to_json_string_ext(obj,flags))) { + if (!(json_str = json_object_to_json_string_ext(obj, flags))) + { return -1; } - wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ + /* CAW: probably unnecessary, but the most 64bit safe */ + wsize = (unsigned int)(strlen(json_str) & UINT_MAX); wpos = 0; - while(wpos < wsize) { - if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { - _json_c_set_last_err("json_object_to_file: error writing file %s: %s\n", - filename, strerror(errno)); - return -1; + while (wpos < wsize) + { + if ((ret = write(fd, json_str + wpos, wsize - wpos)) < 0) + { + _json_c_set_last_err("json_object_to_file: error writing file %s: %s\n", + filename, strerror(errno)); + return -1; } /* because of the above check for ret < 0, we can safely cast and add */ @@ -185,14 +219,15 @@ int json_object_to_file(const char *filename, struct json_object *obj) { - return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN); + return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN); } +// Deprecated json_parse_double function. See json_tokener_parse_double instead. int json_parse_double(const char *buf, double *retval) { - char *end; - *retval = strtod(buf, &end); - return end == buf ? 1 : 0; + char *end; + *retval = strtod(buf, &end); + return end == buf ? 1 : 0; } int json_parse_int64(const char *buf, int64_t *retval) @@ -207,8 +242,25 @@ return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0; } +int json_parse_uint64(const char *buf, uint64_t *retval) +{ + char *end = NULL; + uint64_t val; + + errno = 0; + while (*buf == ' ') + buf++; + if (*buf == '-') + return 1; /* error: uint cannot be negative */ + + val = strtoull(buf, &end, 10); + if (end != buf) + *retval = val; + return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0; +} + #ifndef HAVE_REALLOC -void* rpl_realloc(void* p, size_t n) +void *rpl_realloc(void *p, size_t n) { if (n == 0) n = 1; @@ -218,26 +270,28 @@ } #endif -#define NELEM(a) (sizeof(a) / sizeof(a[0])) -static const char* json_type_name[] = { - /* If you change this, be sure to update the enum json_type definition too */ - "null", - "boolean", - "double", - "int", - "object", - "array", - "string", +#define NELEM(a) (sizeof(a) / sizeof(a[0])) +/* clang-format off */ +static const char *json_type_name[] = { + /* If you change this, be sure to update the enum json_type definition too */ + "null", + "boolean", + "double", + "int", + "object", + "array", + "string", }; +/* clang-format on */ const char *json_type_to_name(enum json_type o_type) { int o_type_int = (int)o_type; if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name)) { - _json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name)); + _json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type, + NELEM(json_type_name)); return NULL; } return json_type_name[o_type]; } - diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_util.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_util.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_util.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_util.h 2022-04-15 07:49:21.000000000 +0000 @@ -12,21 +12,20 @@ /** * @file * @brief Miscllaneous utility functions and macros. - */ + */ #ifndef _json_util_h_ #define _json_util_h_ #include "json_object.h" #ifndef json_min -#define json_min(a,b) ((a) < (b) ? (a) : (b)) +#define json_min(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef json_max -#define json_max(a,b) ((a) > (b) ? (a) : (b)) +#define json_max(a, b) ((a) > (b) ? (a) : (b)) #endif - #ifdef __cplusplus extern "C" { #endif @@ -38,9 +37,9 @@ * Read the full contents of the given file, then convert it to a * json_object using json_tokener_parse(). * - * Returns -1 if something fails. See json_util_get_last_err() for details. + * Returns NULL on failure. See json_util_get_last_err() for details. */ -extern struct json_object* json_object_from_file(const char *filename); +JSON_EXPORT struct json_object *json_object_from_file(const char *filename); /** * Create a JSON object from already opened file descriptor. @@ -50,9 +49,21 @@ * Note, that the fd must be readable at the actual position, i.e. * use lseek(fd, 0, SEEK_SET) before. * - * Returns -1 if something fails. See json_util_get_last_err() for details. + * The depth argument specifies the maximum object depth to pass to + * json_tokener_new_ex(). When depth == -1, JSON_TOKENER_DEFAULT_DEPTH + * is used instead. + * + * Returns NULL on failure. See json_util_get_last_err() for details. + */ +JSON_EXPORT struct json_object *json_object_from_fd_ex(int fd, int depth); + +/** + * Create a JSON object from an already opened file descriptor, using + * the default maximum object depth. (JSON_TOKENER_DEFAULT_DEPTH) + * + * See json_object_from_fd_ex() for details. */ -extern struct json_object* json_object_from_fd(int fd); +JSON_EXPORT struct json_object *json_object_from_fd(int fd); /** * Equivalent to: @@ -60,7 +71,7 @@ * * Returns -1 if something fails. See json_util_get_last_err() for details. */ -extern int json_object_to_file(const char *filename, struct json_object *obj); +JSON_EXPORT int json_object_to_file(const char *filename, struct json_object *obj); /** * Open and truncate the given file, creating it if necessary, then @@ -68,7 +79,7 @@ * * Returns -1 if something fails. See json_util_get_last_err() for details. */ -extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags); +JSON_EXPORT int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags); /** * Convert the json_object to a string and write it to the file descriptor. @@ -80,24 +91,28 @@ * @param flags flags to pass to json_object_to_json_string_ext() * @return -1 if something fails. See json_util_get_last_err() for details. */ -extern int json_object_to_fd(int fd, struct json_object *obj, int flags); +JSON_EXPORT int json_object_to_fd(int fd, struct json_object *obj, int flags); /** * Return the last error from various json-c functions, including: * json_object_to_file{,_ext}, json_object_to_fd() or * json_object_from_{file,fd}, or NULL if there is none. */ -const char *json_util_get_last_err(void); +JSON_EXPORT const char *json_util_get_last_err(void); - -extern int json_parse_int64(const char *buf, int64_t *retval); -extern int json_parse_double(const char *buf, double *retval); +/* these parsing helpers return zero on success */ +JSON_EXPORT int json_parse_int64(const char *buf, int64_t *retval); +JSON_EXPORT int json_parse_uint64(const char *buf, uint64_t *retval); +/** + * @deprecated + */ +JSON_EXPORT int json_parse_double(const char *buf, double *retval); /** * Return a string describing the type of the object. * e.g. "int", or "object", etc... */ -extern const char *json_type_to_name(enum json_type o_type); +JSON_EXPORT const char *json_type_to_name(enum json_type o_type); #ifdef __cplusplus } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_visit.c thunderbird-91.8.1+build1/comm/third_party/json-c/json_visit.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_visit.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_visit.c 2022-04-15 07:49:22.000000000 +0000 @@ -13,45 +13,39 @@ #include "json_visit.h" #include "linkhash.h" -static int _json_c_visit(json_object *jso, json_object *parent_jso, - const char *jso_key, size_t *jso_index, - json_c_visit_userfunc *userfunc, void *userarg); +static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key, + size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg); -int json_c_visit(json_object *jso, int future_flags, - json_c_visit_userfunc *userfunc, void *userarg) +int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *userfunc, void *userarg) { int ret = _json_c_visit(jso, NULL, NULL, NULL, userfunc, userarg); - switch(ret) + switch (ret) { case JSON_C_VISIT_RETURN_CONTINUE: case JSON_C_VISIT_RETURN_SKIP: case JSON_C_VISIT_RETURN_POP: - case JSON_C_VISIT_RETURN_STOP: - return 0; - default: - return JSON_C_VISIT_RETURN_ERROR; + case JSON_C_VISIT_RETURN_STOP: return 0; + default: return JSON_C_VISIT_RETURN_ERROR; } } -static int _json_c_visit(json_object *jso, json_object *parent_jso, - const char *jso_key, size_t *jso_index, - json_c_visit_userfunc *userfunc, void *userarg) +static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key, + size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg) { int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg); - switch(userret) + switch (userret) { - case JSON_C_VISIT_RETURN_CONTINUE: - break; + case JSON_C_VISIT_RETURN_CONTINUE: break; case JSON_C_VISIT_RETURN_SKIP: case JSON_C_VISIT_RETURN_POP: case JSON_C_VISIT_RETURN_STOP: - case JSON_C_VISIT_RETURN_ERROR: - return userret; + case JSON_C_VISIT_RETURN_ERROR: return userret; default: - fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret); + fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", + userret); return JSON_C_VISIT_RETURN_ERROR; } - switch(json_object_get_type(jso)) + switch (json_object_get_type(jso)) { case json_type_null: case json_type_boolean: @@ -69,12 +63,13 @@ if (userret == JSON_C_VISIT_RETURN_POP) break; if (userret == JSON_C_VISIT_RETURN_STOP || - userret == JSON_C_VISIT_RETURN_ERROR) + userret == JSON_C_VISIT_RETURN_ERROR) return userret; if (userret != JSON_C_VISIT_RETURN_CONTINUE && - userret != JSON_C_VISIT_RETURN_SKIP) + userret != JSON_C_VISIT_RETURN_SKIP) { - fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret); + fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", + userret); return JSON_C_VISIT_RETURN_ERROR; } } @@ -91,19 +86,21 @@ if (userret == JSON_C_VISIT_RETURN_POP) break; if (userret == JSON_C_VISIT_RETURN_STOP || - userret == JSON_C_VISIT_RETURN_ERROR) + userret == JSON_C_VISIT_RETURN_ERROR) return userret; if (userret != JSON_C_VISIT_RETURN_CONTINUE && - userret != JSON_C_VISIT_RETURN_SKIP) + userret != JSON_C_VISIT_RETURN_SKIP) { - fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret); + fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", + userret); return JSON_C_VISIT_RETURN_ERROR; } } break; } default: - fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n", json_object_get_type(jso)); + fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n", + json_object_get_type(jso)); return JSON_C_VISIT_RETURN_ERROR; } @@ -112,22 +109,20 @@ // Non-container types will have already returned before this point. userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg); - switch(userret) + switch (userret) { case JSON_C_VISIT_RETURN_SKIP: case JSON_C_VISIT_RETURN_POP: - // These are not really sensible during JSON_C_VISIT_SECOND, + // These are not really sensible during JSON_C_VISIT_SECOND, // but map them to JSON_C_VISIT_CONTINUE anyway. // FALLTHROUGH - case JSON_C_VISIT_RETURN_CONTINUE: - return JSON_C_VISIT_RETURN_CONTINUE; + case JSON_C_VISIT_RETURN_CONTINUE: return JSON_C_VISIT_RETURN_CONTINUE; case JSON_C_VISIT_RETURN_STOP: - case JSON_C_VISIT_RETURN_ERROR: - return userret; + case JSON_C_VISIT_RETURN_ERROR: return userret; default: - fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret); + fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", + userret); return JSON_C_VISIT_RETURN_ERROR; } // NOTREACHED } - diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/json_visit.h thunderbird-91.8.1+build1/comm/third_party/json-c/json_visit.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/json_visit.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/json_visit.h 2022-04-15 07:49:21.000000000 +0000 @@ -8,9 +8,12 @@ */ #include "json_object.h" -typedef int (json_c_visit_userfunc)(json_object *jso, int flags, - json_object *parent_jso, const char *jso_key, - size_t *jso_index, void *userarg); +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(json_c_visit_userfunc)(json_object *jso, int flags, json_object *parent_jso, + const char *jso_key, size_t *jso_index, void *userarg); /** * Visit each object in the JSON hierarchy starting at jso. @@ -26,20 +29,20 @@ * userfunc must return one of the defined return values, to indicate * whether and how to continue visiting nodes, or one of various ways to stop. * - * Returns 0 if nodes were visited successfully, even if some were + * Returns 0 if nodes were visited successfully, even if some were * intentionally skipped due to what userfunc returned. * Returns <0 if an error occurred during iteration, including if * userfunc returned JSON_C_VISIT_RETURN_ERROR. */ -int json_c_visit(json_object *jso, int future_flags, - json_c_visit_userfunc *userfunc, void *userarg); +JSON_EXPORT int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *userfunc, + void *userarg); /** * Passed to json_c_visit_userfunc as one of the flags values to indicate * that this is the second time a container (array or object) is being * called, after all of it's members have been iterated over. */ -#define JSON_C_VISIT_SECOND 0x02 +#define JSON_C_VISIT_SECOND 0x02 /** * This json_c_visit_userfunc return value indicates that iteration @@ -47,7 +50,6 @@ */ #define JSON_C_VISIT_RETURN_CONTINUE 0 - /** * This json_c_visit_userfunc return value indicates that iteration * over the members of the current object should be skipped. @@ -60,7 +62,7 @@ * This json_c_visit_userfunc return value indicates that iteration * of the fields/elements of the containing object should stop * and continue "popped up" a level of the object hierarchy. - * For example, returning this when handling arg will result in + * For example, returning this when handling arg will result in * arg3 and any other fields being skipped. The next call to userfunc * will be the JSON_C_VISIT_SECOND call on "foo", followed by a userfunc * call on "bar". @@ -92,4 +94,8 @@ */ #define JSON_C_VISIT_RETURN_ERROR -1 +#ifdef __cplusplus +} +#endif + #endif /* _json_c_json_visit_h_ */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/libjson.c thunderbird-91.8.1+build1/comm/third_party/json-c/libjson.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/libjson.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/libjson.c 2022-04-15 07:49:21.000000000 +0000 @@ -7,13 +7,13 @@ #ifndef __warn_references -#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG) +#if defined(__GNUC__) && defined(HAS_GNU_WARNING_LONG) -#define __warn_references(sym,msg) \ - __asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text"); +#define __warn_references(sym, msg) \ + __asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text"); #else -#define __warn_references(sym,msg) /* nothing */ +#define __warn_references(sym, msg) /* nothing */ #endif #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/linkhash.c thunderbird-91.8.1+build1/comm/third_party/json-c/linkhash.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/linkhash.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/linkhash.c 2022-04-15 07:49:21.000000000 +0000 @@ -12,55 +12,46 @@ #include "config.h" -#include -#include -#include +#include +#include #include #include -#include +#include +#include +#include #ifdef HAVE_ENDIAN_H -# include /* attempt to define endianness */ +#include /* attempt to define endianness */ #endif #if defined(_MSC_VER) || defined(__MINGW32__) -# define WIN32_LEAN_AND_MEAN -# include /* Get InterlockedCompareExchange */ +#define WIN32_LEAN_AND_MEAN +#include /* Get InterlockedCompareExchange */ #endif -#include "random_seed.h" #include "linkhash.h" +#include "random_seed.h" /* hash functions */ static unsigned long lh_char_hash(const void *k); static unsigned long lh_perllike_str_hash(const void *k); static lh_hash_fn *char_hash_fn = lh_char_hash; -int -json_global_set_string_hash(const int h) +/* comparison functions */ +int lh_char_equal(const void *k1, const void *k2); +int lh_ptr_equal(const void *k1, const void *k2); + +int json_global_set_string_hash(const int h) { - switch(h) { - case JSON_C_STR_HASH_DFLT: - char_hash_fn = lh_char_hash; - break; - case JSON_C_STR_HASH_PERLLIKE: - char_hash_fn = lh_perllike_str_hash; - break; - default: - return -1; + switch (h) + { + case JSON_C_STR_HASH_DFLT: char_hash_fn = lh_char_hash; break; + case JSON_C_STR_HASH_PERLLIKE: char_hash_fn = lh_perllike_str_hash; break; + default: return -1; } return 0; } -void lh_abort(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - vprintf(msg, ap); - va_end(ap); - exit(1); -} - static unsigned long lh_ptr_hash(const void *k) { /* CAW: refactored to be 64bit nice */ @@ -119,25 +110,23 @@ * My best guess at if you are big-endian or little-endian. This may * need adjustment. */ -#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ - __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ - __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(vax) || defined(MIPSEL)) +#define HASH_LITTLE_ENDIAN 1 +#define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +#define HASH_LITTLE_ENDIAN 0 +#define HASH_BIG_ENDIAN 1 #else -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 0 +#define HASH_LITTLE_ENDIAN 0 +#define HASH_BIG_ENDIAN 0 #endif -#define hashsize(n) ((uint32_t)1<<(n)) -#define hashmask(n) (hashsize(n)-1) -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) +#define hashsize(n) ((uint32_t)1 << (n)) +#define hashmask(n) (hashsize(n) - 1) +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) /* ------------------------------------------------------------------------------- @@ -183,15 +172,17 @@ rotates. ------------------------------------------------------------------------------- */ +/* clang-format off */ #define mix(a,b,c) \ { \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ } +/* clang-format on */ /* ------------------------------------------------------------------------------- @@ -218,17 +209,18 @@ 11 8 15 26 3 22 24 ------------------------------------------------------------------------------- */ +/* clang-format off */ #define final(a,b,c) \ { \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ } - +/* clang-format on */ /* ------------------------------------------------------------------------------- @@ -257,197 +249,208 @@ ------------------------------------------------------------------------------- */ -static uint32_t hashlittle( const void *key, size_t length, uint32_t initval) +/* clang-format off */ +static uint32_t hashlittle(const void *key, size_t length, uint32_t initval) { - uint32_t a,b,c; /* internal state */ - union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ + uint32_t a,b,c; /* internal state */ + union + { + const void *ptr; + size_t i; + } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ - /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } - u.ptr = key; - if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ - - /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 12; - k += 3; - } - - /*----------------------------- handle the last (probably partial) block */ - /* - * "k[2]&0xffffff" actually reads beyond the end of the string, but - * then masks off the part it's not allowed to read. Because the - * string is aligned, the masked-off tail is in the same word as the - * rest of the string. Every machine with memory protection I've seen - * does it on word boundaries, so is OK with this. But VALGRIND will - * still catch it and complain. The masking trick does make the hash - * noticably faster for short strings (like English words). - * AddressSanitizer is similarly picky about overrunning - * the buffer. (http://clang.llvm.org/docs/AddressSanitizer.html - */ + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + * AddressSanitizer is similarly picky about overrunning + * the buffer. (http://clang.llvm.org/docs/AddressSanitizer.html + */ #ifdef VALGRIND -# define PRECISE_MEMORY_ACCESS 1 +#define PRECISE_MEMORY_ACCESS 1 #elif defined(__SANITIZE_ADDRESS__) /* GCC's ASAN */ -# define PRECISE_MEMORY_ACCESS 1 +#define PRECISE_MEMORY_ACCESS 1 #elif defined(__has_feature) -# if __has_feature(address_sanitizer) /* Clang's ASAN */ -# define PRECISE_MEMORY_ACCESS 1 -# endif +#if __has_feature(address_sanitizer) /* Clang's ASAN */ +#define PRECISE_MEMORY_ACCESS 1 +#endif #endif #ifndef PRECISE_MEMORY_ACCESS - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff; a+=k[0]; break; - case 6 : b+=k[1]&0xffff; a+=k[0]; break; - case 5 : b+=k[1]&0xff; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff; break; - case 2 : a+=k[0]&0xffff; break; - case 1 : a+=k[0]&0xff; break; - case 0 : return c; /* zero length strings require no mixing */ - } + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } #else /* make valgrind happy */ - const uint8_t *k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ - case 1 : a+=k8[0]; break; - case 0 : return c; - } + const uint8_t *k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } #endif /* !valgrind */ - } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ - const uint8_t *k8; - - /*--------------- all but last block: aligned reads and different mixing */ - while (length > 12) - { - a += k[0] + (((uint32_t)k[1])<<16); - b += k[2] + (((uint32_t)k[3])<<16); - c += k[4] + (((uint32_t)k[5])<<16); - mix(a,b,c); - length -= 12; - k += 6; - } - - /*----------------------------- handle the last (probably partial) block */ - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[4]+(((uint32_t)k[5])<<16); - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=k[4]; - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=k[2]; - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=k[0]; - break; - case 1 : a+=k8[0]; - break; - case 0 : return c; /* zero length requires no mixing */ - } - - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - a += ((uint32_t)k[1])<<8; - a += ((uint32_t)k[2])<<16; - a += ((uint32_t)k[3])<<24; - b += k[4]; - b += ((uint32_t)k[5])<<8; - b += ((uint32_t)k[6])<<16; - b += ((uint32_t)k[7])<<24; - c += k[8]; - c += ((uint32_t)k[9])<<8; - c += ((uint32_t)k[10])<<16; - c += ((uint32_t)k[11])<<24; - mix(a,b,c); - length -= 12; - k += 12; - } - - /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ - { - case 12: c+=((uint32_t)k[11])<<24; /* FALLTHRU */ - case 11: c+=((uint32_t)k[10])<<16; /* FALLTHRU */ - case 10: c+=((uint32_t)k[9])<<8; /* FALLTHRU */ - case 9 : c+=k[8]; /* FALLTHRU */ - case 8 : b+=((uint32_t)k[7])<<24; /* FALLTHRU */ - case 7 : b+=((uint32_t)k[6])<<16; /* FALLTHRU */ - case 6 : b+=((uint32_t)k[5])<<8; /* FALLTHRU */ - case 5 : b+=k[4]; /* FALLTHRU */ - case 4 : a+=((uint32_t)k[3])<<24; /* FALLTHRU */ - case 3 : a+=((uint32_t)k[2])<<16; /* FALLTHRU */ - case 2 : a+=((uint32_t)k[1])<<8; /* FALLTHRU */ - case 1 : a+=k[0]; - break; - case 0 : return c; - } - } + } + else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) + { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } - final(a,b,c); - return c; + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } + else + { + /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; /* FALLTHRU */ + case 11: c+=((uint32_t)k[10])<<16; /* FALLTHRU */ + case 10: c+=((uint32_t)k[9])<<8; /* FALLTHRU */ + case 9 : c+=k[8]; /* FALLTHRU */ + case 8 : b+=((uint32_t)k[7])<<24; /* FALLTHRU */ + case 7 : b+=((uint32_t)k[6])<<16; /* FALLTHRU */ + case 6 : b+=((uint32_t)k[5])<<8; /* FALLTHRU */ + case 5 : b+=k[4]; /* FALLTHRU */ + case 4 : a+=((uint32_t)k[3])<<24; /* FALLTHRU */ + case 3 : a+=((uint32_t)k[2])<<16; /* FALLTHRU */ + case 2 : a+=((uint32_t)k[1])<<8; /* FALLTHRU */ + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; } +/* clang-format on */ /* a simple hash function similiar to what perl does for strings. * for good results, the string should not be excessivly large. */ -static unsigned long lh_perllike_str_hash(const void *k) +static unsigned long lh_perllike_str_hash(const void *k) { - const char *rkey = (const char *)k; - unsigned hashval = 1; + const char *rkey = (const char *)k; + unsigned hashval = 1; - while (*rkey) - hashval = hashval * 33 + *rkey++; + while (*rkey) + hashval = hashval * 33 + *rkey++; - return hashval; + return hashval; } static unsigned long lh_char_hash(const void *k) @@ -459,10 +462,11 @@ #endif static volatile RANDOM_SEED_TYPE random_seed = -1; - if (random_seed == -1) { + if (random_seed == -1) + { RANDOM_SEED_TYPE seed; /* we can't use -1 as it is the unitialized sentinel */ - while ((seed = json_c_get_random_seed()) == -1); + while ((seed = json_c_get_random_seed()) == -1) {} #if SIZEOF_INT == 8 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 #define USE_SYNC_COMPARE_AND_SWAP 1 #endif @@ -477,34 +481,34 @@ #elif defined _MSC_VER || defined __MINGW32__ InterlockedCompareExchange(&random_seed, seed, -1); #else -//#warning "racy random seed initializtion if used by multiple threads" + //#warning "racy random seed initializtion if used by multiple threads" random_seed = seed; /* potentially racy */ #endif } - return hashlittle((const char*)k, strlen((const char*)k), random_seed); + return hashlittle((const char *)k, strlen((const char *)k), random_seed); } int lh_char_equal(const void *k1, const void *k2) { - return (strcmp((const char*)k1, (const char*)k2) == 0); + return (strcmp((const char *)k1, (const char *)k2) == 0); } -struct lh_table* lh_table_new(int size, - lh_entry_free_fn *free_fn, - lh_hash_fn *hash_fn, - lh_equal_fn *equal_fn) +struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *hash_fn, + lh_equal_fn *equal_fn) { int i; struct lh_table *t; - t = (struct lh_table*)calloc(1, sizeof(struct lh_table)); + /* Allocate space for elements to avoid divisions by zero. */ + assert(size > 0); + t = (struct lh_table *)calloc(1, sizeof(struct lh_table)); if (!t) return NULL; t->count = 0; t->size = size; - t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry)); + t->table = (struct lh_entry *)calloc(size, sizeof(struct lh_entry)); if (!t->table) { free(t); @@ -513,18 +517,17 @@ t->free_fn = free_fn; t->hash_fn = hash_fn; t->equal_fn = equal_fn; - for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY; + for (i = 0; i < size; i++) + t->table[i].k = LH_EMPTY; return t; } -struct lh_table* lh_kchar_table_new(int size, - lh_entry_free_fn *free_fn) +struct lh_table *lh_kchar_table_new(int size, lh_entry_free_fn *free_fn) { return lh_table_new(size, free_fn, char_hash_fn, lh_char_equal); } -struct lh_table* lh_kptr_table_new(int size, - lh_entry_free_fn *free_fn) +struct lh_table *lh_kptr_table_new(int size, lh_entry_free_fn *free_fn) { return lh_table_new(size, free_fn, lh_ptr_hash, lh_ptr_equal); } @@ -563,28 +566,36 @@ void lh_table_free(struct lh_table *t) { struct lh_entry *c; - if(t->free_fn) { - for(c = t->head; c != NULL; c = c->next) + if (t->free_fn) + { + for (c = t->head; c != NULL; c = c->next) t->free_fn(c); } free(t->table); free(t); } - -int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts) +int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, + const unsigned opts) { unsigned long n; if (t->count >= t->size * LH_LOAD_FACTOR) - if (lh_table_resize(t, t->size * 2) != 0) + { + /* Avoid signed integer overflow with large tables. */ + int new_size = (t->size > INT_MAX / 2) ? INT_MAX : (t->size * 2); + if (t->size == INT_MAX || lh_table_resize(t, new_size) != 0) return -1; + } n = h % t->size; - while( 1 ) { - if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break; - if ((int)++n == t->size) n = 0; + while (1) + { + if (t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) + break; + if ((int)++n == t->size) + n = 0; } t->table[n].k = k; @@ -592,10 +603,13 @@ t->table[n].v = v; t->count++; - if(t->head == NULL) { + if (t->head == NULL) + { t->head = t->tail = &t->table[n]; t->table[n].next = t->table[n].prev = NULL; - } else { + } + else + { t->tail->next = &t->table[n]; t->table[n].prev = t->tail; t->table[n].next = NULL; @@ -609,66 +623,78 @@ return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k), 0); } - -struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h) +struct lh_entry *lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, + const unsigned long h) { unsigned long n = h % t->size; int count = 0; - while( count < t->size ) { - if(t->table[n].k == LH_EMPTY) return NULL; - if(t->table[n].k != LH_FREED && - t->equal_fn(t->table[n].k, k)) return &t->table[n]; - if ((int)++n == t->size) n = 0; + while (count < t->size) + { + if (t->table[n].k == LH_EMPTY) + return NULL; + if (t->table[n].k != LH_FREED && t->equal_fn(t->table[n].k, k)) + return &t->table[n]; + if ((int)++n == t->size) + n = 0; count++; } return NULL; } -struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k) +struct lh_entry *lh_table_lookup_entry(struct lh_table *t, const void *k) { return lh_table_lookup_entry_w_hash(t, k, lh_get_hash(t, k)); } -const void* lh_table_lookup(struct lh_table *t, const void *k) -{ - void *result; - lh_table_lookup_ex(t, k, &result); - return result; -} - -json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v) +json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v) { struct lh_entry *e = lh_table_lookup_entry(t, k); - if (e != NULL) { - if (v != NULL) *v = lh_entry_v(e); - return TRUE; /* key found */ + if (e != NULL) + { + if (v != NULL) + *v = lh_entry_v(e); + return 1; /* key found */ } - if (v != NULL) *v = NULL; - return FALSE; /* key not found */ + if (v != NULL) + *v = NULL; + return 0; /* key not found */ } int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) { - ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */ + /* CAW: fixed to be 64bit nice, still need the crazy negative case... */ + ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ - if(n < 0) { return -2; } + if (n < 0) + { + return -2; + } - if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1; + if (t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) + return -1; t->count--; - if(t->free_fn) t->free_fn(e); + if (t->free_fn) + t->free_fn(e); t->table[n].v = NULL; t->table[n].k = LH_FREED; - if(t->tail == &t->table[n] && t->head == &t->table[n]) { + if (t->tail == &t->table[n] && t->head == &t->table[n]) + { t->head = t->tail = NULL; - } else if (t->head == &t->table[n]) { + } + else if (t->head == &t->table[n]) + { t->head->next->prev = NULL; t->head = t->head->next; - } else if (t->tail == &t->table[n]) { + } + else if (t->tail == &t->table[n]) + { t->tail->prev->next = NULL; t->tail = t->tail->prev; - } else { + } + else + { t->table[n].prev->next = t->table[n].next; t->table[n].next->prev = t->table[n].prev; } @@ -676,11 +702,11 @@ return 0; } - int lh_table_delete(struct lh_table *t, const void *k) { struct lh_entry *e = lh_table_lookup_entry(t, k); - if(!e) return -1; + if (!e) + return -1; return lh_table_delete_entry(t, e); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/linkhash.h thunderbird-91.8.1+build1/comm/third_party/json-c/linkhash.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/linkhash.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/linkhash.h 2022-04-15 07:49:21.000000000 +0000 @@ -40,12 +40,12 @@ /** * sentinel pointer value for empty slots */ -#define LH_EMPTY (void*)-1 +#define LH_EMPTY (void *)-1 /** * sentinel pointer value for freed slots */ -#define LH_FREED (void*)-2 +#define LH_FREED (void *)-2 /** * default string hash function @@ -69,20 +69,21 @@ /** * callback function prototypes */ -typedef void (lh_entry_free_fn) (struct lh_entry *e); +typedef void(lh_entry_free_fn)(struct lh_entry *e); /** * callback function prototypes */ -typedef unsigned long (lh_hash_fn) (const void *k); +typedef unsigned long(lh_hash_fn)(const void *k); /** * callback function prototypes */ -typedef int (lh_equal_fn) (const void *k1, const void *k2); +typedef int(lh_equal_fn)(const void *k1, const void *k2); /** * An entry in the hash table */ -struct lh_entry { +struct lh_entry +{ /** * The key. Use lh_entry_k() instead of accessing this directly. */ @@ -106,11 +107,11 @@ struct lh_entry *prev; }; - /** * The hash table structure. */ -struct lh_table { +struct lh_table +{ /** * Size of our hash. */ @@ -141,12 +142,10 @@ }; typedef struct lh_table lh_table; - /** * Convenience list iterator. */ -#define lh_foreach(table, entry) \ -for(entry = table->head; entry; entry = entry->next) +#define lh_foreach(table, entry) for (entry = table->head; entry; entry = entry->next) /** * lh_foreach_safe allows calling of deletion routine while iterating. @@ -156,9 +155,7 @@ * @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element */ #define lh_foreach_safe(table, entry, tmp) \ -for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp) - - + for (entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp) /** * Create a new linkhash table. @@ -178,10 +175,8 @@ * @return On success, a pointer to the new linkhash table is returned. * On error, a null pointer is returned. */ -extern struct lh_table* lh_table_new(int size, - lh_entry_free_fn *free_fn, - lh_hash_fn *hash_fn, - lh_equal_fn *equal_fn); +extern struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *hash_fn, + lh_equal_fn *equal_fn); /** * Convenience function to create a new linkhash table with char keys. @@ -191,9 +186,7 @@ * @return On success, a pointer to the new linkhash table is returned. * On error, a null pointer is returned. */ -extern struct lh_table* lh_kchar_table_new(int size, - lh_entry_free_fn *free_fn); - +extern struct lh_table *lh_kchar_table_new(int size, lh_entry_free_fn *free_fn); /** * Convenience function to create a new linkhash table with ptr keys. @@ -203,9 +196,7 @@ * @return On success, a pointer to the new linkhash table is returned. * On error, a null pointer is returned. */ -extern struct lh_table* lh_kptr_table_new(int size, - lh_entry_free_fn *free_fn); - +extern struct lh_table *lh_kptr_table_new(int size, lh_entry_free_fn *free_fn); /** * Free a linkhash table. @@ -217,7 +208,6 @@ */ extern void lh_table_free(struct lh_table *t); - /** * Insert a record into the table. * @@ -230,7 +220,6 @@ */ extern int lh_table_insert(struct lh_table *t, const void *k, const void *v); - /** * Insert a record into the table using a precalculated key hash. * @@ -245,8 +234,8 @@ * @param opts if set to JSON_C_OBJECT_KEY_IS_CONSTANT, sets lh_entry.k_is_constant * so t's free function knows to avoid freeing the key. */ -extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts); - +extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, + const unsigned long h, const unsigned opts); /** * Lookup a record in the table. @@ -255,7 +244,7 @@ * @param k a pointer to the key to lookup * @return a pointer to the record structure of the value or NULL if it does not exist. */ -extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k); +extern struct lh_entry *lh_table_lookup_entry(struct lh_table *t, const void *k); /** * Lookup a record in the table using a precalculated key hash. @@ -269,17 +258,8 @@ * @param h hash value of the key to lookup * @return a pointer to the record structure of the value or NULL if it does not exist. */ -extern struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h); - -/** - * Lookup a record into the table. - * - * @param t the table to lookup - * @param k a pointer to the key to lookup - * @return a pointer to the found value or NULL if it does not exist. - * @deprecated Use lh_table_lookup_ex() instead. - */ -THIS_FUNCTION_IS_DEPRECATED(extern const void* lh_table_lookup(struct lh_table *t, const void *k)); +extern struct lh_entry *lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, + const unsigned long h); /** * Lookup a record in the table. @@ -303,7 +283,6 @@ */ extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); - /** * Delete a record from the table. * @@ -319,21 +298,6 @@ extern int lh_table_length(struct lh_table *t); /** - * Prints a message to stdout, - * then exits the program with an exit code of 1. - * - * @param msg Message format string, like for printf. - * @param ... Format args. - * - * @deprecated Since it is not a good idea to exit the entire program - * because of an internal library failure, json-c will no longer - * use this function internally. - * However, because its interface is public, it will remain part of - * the API on the off chance of legacy software using it externally. - */ -THIS_FUNCTION_IS_DEPRECATED(void lh_abort(const char *msg, ...)); - -/** * Resizes the specified table. * * @param t Pointer to table to resize. @@ -344,15 +308,14 @@ */ int lh_table_resize(struct lh_table *t, int new_size); - /** * @deprecated Don't use this outside of linkhash.h: */ -#if !defined(_MSC_VER) || (_MSC_VER > 1800) +#if (defined(AIX_CC) || (defined(_MSC_VER) && (_MSC_VER <= 1800)) ) /* VS2010 can't handle inline funcs, so skip it there */ -#define _LH_INLINE inline -#else #define _LH_INLINE +#else +#define _LH_INLINE inline #endif /** diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/math_compat.h thunderbird-91.8.1+build1/comm/third_party/json-c/math_compat.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/math_compat.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/math_compat.h 2022-04-15 07:49:21.000000000 +0000 @@ -9,17 +9,24 @@ /* Define isnan, isinf, infinity and nan on Windows/MSVC */ #ifndef HAVE_DECL_ISNAN -# ifdef HAVE_DECL__ISNAN +#ifdef HAVE_DECL__ISNAN #include #define isnan(x) _isnan(x) -# endif +#else +/* On platforms like AIX and "IBM i" we need to provide our own isnan */ +#define isnan(x) ((x) != (x)) +#endif #endif #ifndef HAVE_DECL_ISINF -# ifdef HAVE_DECL__FINITE +#ifdef HAVE_DECL__FINITE #include #define isinf(x) (!_finite(x)) -# endif +#else +#include +/* On platforms like AIX and "IBM i" we need to provide our own isinf */ +#define isinf(x) ((x) < -DBL_MAX || (x) > DBL_MAX) +#endif #endif #ifndef HAVE_DECL_INFINITY diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/printbuf.c thunderbird-91.8.1+build1/comm/third_party/json-c/printbuf.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/printbuf.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/printbuf.c 2022-04-15 07:49:21.000000000 +0000 @@ -15,14 +15,15 @@ #include "config.h" +#include #include #include #include #ifdef HAVE_STDARG_H -# include +#include #else /* !HAVE_STDARG_H */ -# error Not enough var arg support! +#error Not enough var arg support! #endif /* HAVE_STDARG_H */ #include "debug.h" @@ -32,23 +33,24 @@ static int printbuf_extend(struct printbuf *p, int min_size); -struct printbuf* printbuf_new(void) +struct printbuf *printbuf_new(void) { - struct printbuf *p; + struct printbuf *p; - p = (struct printbuf*)calloc(1, sizeof(struct printbuf)); - if(!p) return NULL; - p->size = 32; - p->bpos = 0; - if(!(p->buf = (char*)malloc(p->size))) { - free(p); - return NULL; - } - p->buf[0]= '\0'; - return p; + p = (struct printbuf *)calloc(1, sizeof(struct printbuf)); + if (!p) + return NULL; + p->size = 32; + p->bpos = 0; + if (!(p->buf = (char *)malloc(p->size))) + { + free(p); + return NULL; + } + p->buf[0] = '\0'; + return p; } - /** * Extend the buffer p so it has a size of at least min_size. * @@ -64,16 +66,22 @@ if (p->size >= min_size) return 0; - - new_size = p->size * 2; - if (new_size < min_size + 8) - new_size = min_size + 8; + /* Prevent signed integer overflows with large buffers. */ + if (min_size > INT_MAX - 8) + return -1; + if (p->size > INT_MAX / 2) + new_size = min_size + 8; + else { + new_size = p->size * 2; + if (new_size < min_size + 8) + new_size = min_size + 8; + } #ifdef PRINTBUF_DEBUG MC_DEBUG("printbuf_memappend: realloc " - "bpos=%d min_size=%d old_size=%d new_size=%d\n", - p->bpos, min_size, p->size, new_size); + "bpos=%d min_size=%d old_size=%d new_size=%d\n", + p->bpos, min_size, p->size, new_size); #endif /* PRINTBUF_DEBUG */ - if(!(t = (char*)realloc(p->buf, new_size))) + if (!(t = (char *)realloc(p->buf, new_size))) return -1; p->size = new_size; p->buf = t; @@ -82,14 +90,18 @@ int printbuf_memappend(struct printbuf *p, const char *buf, int size) { - if (p->size <= p->bpos + size + 1) { - if (printbuf_extend(p, p->bpos + size + 1) < 0) - return -1; - } - memcpy(p->buf + p->bpos, buf, size); - p->bpos += size; - p->buf[p->bpos]= '\0'; - return size; + /* Prevent signed integer overflows with large buffers. */ + if (size > INT_MAX - p->bpos - 1) + return -1; + if (p->size <= p->bpos + size + 1) + { + if (printbuf_extend(p, p->bpos + size + 1) < 0) + return -1; + } + memcpy(p->buf + p->bpos, buf, size); + p->bpos += size; + p->buf[p->bpos] = '\0'; + return size; } int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len) @@ -98,6 +110,9 @@ if (offset == -1) offset = pb->bpos; + /* Prevent signed integer overflows with large buffers. */ + if (len > INT_MAX - offset) + return -1; size_needed = offset + len; if (pb->size < size_needed) { @@ -114,42 +129,51 @@ int sprintbuf(struct printbuf *p, const char *msg, ...) { - va_list ap; - char *t; - int size; - char buf[128]; - - /* user stack buffer first */ - va_start(ap, msg); - size = vsnprintf(buf, 128, msg, ap); - va_end(ap); - /* if string is greater than stack buffer, then use dynamic string - with vasprintf. Note: some implementation of vsnprintf return -1 - if output is truncated whereas some return the number of bytes that - would have been written - this code handles both cases. */ - if(size == -1 || size > 127) { - va_start(ap, msg); - if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } - va_end(ap); - printbuf_memappend(p, t, size); - free(t); - return size; - } else { - printbuf_memappend(p, buf, size); - return size; - } + va_list ap; + char *t; + int size; + char buf[128]; + + /* user stack buffer first */ + va_start(ap, msg); + size = vsnprintf(buf, 128, msg, ap); + va_end(ap); + /* if string is greater than stack buffer, then use dynamic string + * with vasprintf. Note: some implementation of vsnprintf return -1 + * if output is truncated whereas some return the number of bytes that + * would have been written - this code handles both cases. + */ + if (size == -1 || size > 127) + { + va_start(ap, msg); + if ((size = vasprintf(&t, msg, ap)) < 0) + { + va_end(ap); + return -1; + } + va_end(ap); + printbuf_memappend(p, t, size); + free(t); + return size; + } + else + { + printbuf_memappend(p, buf, size); + return size; + } } void printbuf_reset(struct printbuf *p) { - p->buf[0] = '\0'; - p->bpos = 0; + p->buf[0] = '\0'; + p->bpos = 0; } void printbuf_free(struct printbuf *p) { - if(p) { - free(p->buf); - free(p); - } + if (p) + { + free(p->buf); + free(p); + } } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/printbuf.h thunderbird-91.8.1+build1/comm/third_party/json-c/printbuf.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/printbuf.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/printbuf.h 2022-04-15 07:49:22.000000000 +0000 @@ -15,7 +15,7 @@ /** * @file - * @brief Internal string buffer handing. Unless you're writing a + * @brief Internal string buffer handing. Unless you're writing a * json_object_to_json_string_fn implementation for use with * json_object_set_serializer() direct use of this is not * recommended. @@ -23,19 +23,27 @@ #ifndef _printbuf_h_ #define _printbuf_h_ +#ifndef JSON_EXPORT +#if defined(_MSC_VER) +#define JSON_EXPORT __declspec(dllexport) +#else +#define JSON_EXPORT extern +#endif +#endif + #ifdef __cplusplus extern "C" { #endif -struct printbuf { - char *buf; - int bpos; - int size; +struct printbuf +{ + char *buf; + int bpos; + int size; }; typedef struct printbuf printbuf; -extern struct printbuf* -printbuf_new(void); +JSON_EXPORT struct printbuf *printbuf_new(void); /* As an optimization, printbuf_memappend_fast() is defined as a macro * that handles copying data if the buffer is large enough; otherwise @@ -45,17 +53,22 @@ * Your code should not use printbuf_memappend() directly unless it * checks the return code. Use printbuf_memappend_fast() instead. */ -extern int -printbuf_memappend(struct printbuf *p, const char *buf, int size); +JSON_EXPORT int printbuf_memappend(struct printbuf *p, const char *buf, int size); -#define printbuf_memappend_fast(p, bufptr, bufsize) \ -do { \ - if ((p->size - p->bpos) > bufsize) { \ - memcpy(p->buf + p->bpos, (bufptr), bufsize); \ - p->bpos += bufsize; \ - p->buf[p->bpos]= '\0'; \ - } else { printbuf_memappend(p, (bufptr), bufsize); } \ -} while (0) +#define printbuf_memappend_fast(p, bufptr, bufsize) \ + do \ + { \ + if ((p->size - p->bpos) > bufsize) \ + { \ + memcpy(p->buf + p->bpos, (bufptr), bufsize); \ + p->bpos += bufsize; \ + p->buf[p->bpos] = '\0'; \ + } \ + else \ + { \ + printbuf_memappend(p, (bufptr), bufsize); \ + } \ + } while (0) #define printbuf_length(p) ((p)->bpos) @@ -79,7 +92,7 @@ * sprintbuf() */ #define printbuf_strappend(pb, str) \ - printbuf_memappend ((pb), _printbuf_check_literal(str), sizeof(str) - 1) + printbuf_memappend((pb), _printbuf_check_literal(str), sizeof(str) - 1) /** * Set len bytes of the buffer to charvalue, starting at offset offset. @@ -89,8 +102,7 @@ * * If offset is -1, this starts at the end of the current data in the buffer. */ -extern int -printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len); +JSON_EXPORT int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len); /** * Formatted print to printbuf. @@ -106,14 +118,11 @@ * printbuf_memappend() * printbuf_strappend() */ -extern int -sprintbuf(struct printbuf *p, const char *msg, ...); +JSON_EXPORT int sprintbuf(struct printbuf *p, const char *msg, ...); -extern void -printbuf_reset(struct printbuf *p); +JSON_EXPORT void printbuf_reset(struct printbuf *p); -extern void -printbuf_free(struct printbuf *p); +JSON_EXPORT void printbuf_free(struct printbuf *p); #ifdef __cplusplus } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/random_seed.c thunderbird-91.8.1+build1/comm/third_party/json-c/random_seed.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/random_seed.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/random_seed.c 2022-04-15 07:49:21.000000000 +0000 @@ -9,14 +9,13 @@ * */ +#include "random_seed.h" +#include "config.h" #include "strerror_override.h" #include -#include "config.h" -#include "random_seed.h" #define DEBUG_SEED(s) - #if defined ENABLE_RDRAND /* cpuid */ @@ -26,20 +25,11 @@ static void do_cpuid(int regs[], int h) { - __asm__ __volatile__( -#if defined __x86_64__ - "pushq %%rbx;\n" -#else - "pushl %%ebx;\n" -#endif - "cpuid;\n" -#if defined __x86_64__ - "popq %%rbx;\n" -#else - "popl %%ebx;\n" -#endif - : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) + /* clang-format off */ + __asm__ __volatile__("cpuid" + : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) : "a"(h)); + /* clang-format on */ } #elif defined _MSC_VER @@ -53,12 +43,51 @@ #if HAS_X86_CPUID -static int has_rdrand() +static int get_rdrand_seed(void); + +/* Valid values are -1 (haven't tested), 0 (no), and 1 (yes). */ +static int _has_rdrand = -1; + +static int has_rdrand(void) { - // CPUID.01H:ECX.RDRAND[bit 30] == 1 - int regs[4]; - do_cpuid(regs, 1); - return (regs[2] & (1 << 30)) != 0; + if (_has_rdrand != -1) + { + return _has_rdrand; + } + + /* CPUID.01H:ECX.RDRAND[bit 30] == 1 */ + int regs[4]; + do_cpuid(regs, 1); + if (!(regs[2] & (1 << 30))) + { + _has_rdrand = 0; + return 0; + } + + /* + * Some CPUs advertise RDRAND in CPUID, but return 0xFFFFFFFF + * unconditionally. To avoid locking up later, test RDRAND here. If over + * 3 trials RDRAND has returned the same value, declare it broken. + * Example CPUs are AMD Ryzen 3000 series + * and much older AMD APUs, such as the E1-1500 + * https://github.com/systemd/systemd/issues/11810 + * https://linuxreviews.org/RDRAND_stops_returning_random_values_on_older_AMD_CPUs_after_suspend + */ + _has_rdrand = 0; + int prev = get_rdrand_seed(); + for (int i = 0; i < 3; i++) + { + int temp = get_rdrand_seed(); + if (temp != prev) + { + _has_rdrand = 1; + break; + } + + prev = temp; + } + + return _has_rdrand; } #endif @@ -69,17 +98,19 @@ #define HAVE_RDRAND 1 -static int get_rdrand_seed() +static int get_rdrand_seed(void) { - DEBUG_SEED("get_rdrand_seed"); - int _eax; - // rdrand eax - __asm__ __volatile__("1: .byte 0x0F\n" - " .byte 0xC7\n" - " .byte 0xF0\n" - " jnc 1b;\n" - : "=a" (_eax)); - return _eax; + DEBUG_SEED("get_rdrand_seed"); + int _eax; + /* rdrand eax */ + /* clang-format off */ + __asm__ __volatile__("1: .byte 0x0F\n" + " .byte 0xC7\n" + " .byte 0xF0\n" + " jnc 1b;\n" + : "=a" (_eax)); + /* clang-format on */ + return _eax; } #endif @@ -91,12 +122,13 @@ /* get_rdrand_seed - Visual Studio 2012 and above */ -static int get_rdrand_seed() +static int get_rdrand_seed(void) { - DEBUG_SEED("get_rdrand_seed"); - int r; - while (_rdrand32_step(&r) == 0); - return r; + DEBUG_SEED("get_rdrand_seed"); + int r; + while (_rdrand32_step(&r) == 0) + ; + return r; } #elif defined _M_IX86 @@ -104,31 +136,34 @@ /* get_rdrand_seed - Visual Studio 2010 and below - x86 only */ -static int get_rdrand_seed() +/* clang-format off */ +static int get_rdrand_seed(void) { DEBUG_SEED("get_rdrand_seed"); int _eax; retry: - // rdrand eax + /* rdrand eax */ __asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0 __asm jnc retry __asm mov _eax, eax return _eax; } +/* clang-format on */ #endif #endif #endif /* defined ENABLE_RDRAND */ - /* has_dev_urandom */ -#if defined (__APPLE__) || defined(__unix__) || defined(__linux__) +#if defined(__APPLE__) || defined(__unix__) || defined(__linux__) -#include #include +#include +#if HAVE_UNISTD_H #include +#endif /* HAVE_UNISTD_H */ #include #include @@ -136,103 +171,124 @@ static const char *dev_random_file = "/dev/urandom"; -static int has_dev_urandom() +static int has_dev_urandom(void) { - struct stat buf; - if (stat(dev_random_file, &buf)) { - return 0; - } - return ((buf.st_mode & S_IFCHR) != 0); + struct stat buf; + if (stat(dev_random_file, &buf)) + { + return 0; + } + return ((buf.st_mode & S_IFCHR) != 0); } - /* get_dev_random_seed */ -static int get_dev_random_seed() +static int get_dev_random_seed(void) { - DEBUG_SEED("get_dev_random_seed"); + DEBUG_SEED("get_dev_random_seed"); - int fd = open(dev_random_file, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); - exit(1); - } - - int r; - ssize_t nread = read(fd, &r, sizeof(r)); - if (nread != sizeof(r)) { - fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno)); - exit(1); - } + int fd = open(dev_random_file, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); + exit(1); + } + + int r; + ssize_t nread = read(fd, &r, sizeof(r)); + if (nread != sizeof(r)) + { + fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno)); + exit(1); + } - close(fd); - return r; + close(fd); + return r; } #endif - /* get_cryptgenrandom_seed */ #ifdef WIN32 #define HAVE_CRYPTGENRANDOM 1 +/* clang-format off */ #include + +/* Caution: these blank lines must remain so clang-format doesn't reorder + includes to put windows.h after wincrypt.h */ + #include +/* clang-format on */ #ifndef __GNUC__ #pragma comment(lib, "advapi32.lib") #endif -static int get_cryptgenrandom_seed() -{ - HCRYPTPROV hProvider = 0; - int r; - - DEBUG_SEED("get_cryptgenrandom_seed"); - - if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { - fprintf(stderr, "error CryptAcquireContextW"); - exit(1); - } +static int get_time_seed(void); - if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) { - fprintf(stderr, "error CryptGenRandom"); - exit(1); - } - - CryptReleaseContext(hProvider, 0); +static int get_cryptgenrandom_seed(void) +{ + HCRYPTPROV hProvider = 0; + DWORD dwFlags = CRYPT_VERIFYCONTEXT; + int r; + + DEBUG_SEED("get_cryptgenrandom_seed"); + + /* WinNT 4 and Win98 do no support CRYPT_SILENT */ + if (LOBYTE(LOWORD(GetVersion())) > 4) + dwFlags |= CRYPT_SILENT; + + if (!CryptAcquireContextA(&hProvider, 0, 0, PROV_RSA_FULL, dwFlags)) + { + fprintf(stderr, "error CryptAcquireContextA 0x%08lx", GetLastError()); + r = get_time_seed(); + } + else + { + BOOL ret = CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r); + CryptReleaseContext(hProvider, 0); + if (!ret) + { + fprintf(stderr, "error CryptGenRandom 0x%08lx", GetLastError()); + r = get_time_seed(); + } + } - return r; + return r; } #endif - /* get_time_seed */ #include -static int get_time_seed() +static int get_time_seed(void) { - DEBUG_SEED("get_time_seed"); + DEBUG_SEED("get_time_seed"); - return (int)time(NULL) * 433494437; + return (int)time(NULL) * 433494437; } - /* json_c_get_random_seed */ -int json_c_get_random_seed() +int json_c_get_random_seed(void) { -#if HAVE_RDRAND - if (has_rdrand()) return get_rdrand_seed(); +#ifdef OVERRIDE_GET_RANDOM_SEED + OVERRIDE_GET_RANDOM_SEED; +#endif +#if defined HAVE_RDRAND && HAVE_RDRAND + if (has_rdrand()) + return get_rdrand_seed(); #endif -#if HAVE_DEV_RANDOM - if (has_dev_urandom()) return get_dev_random_seed(); +#if defined HAVE_DEV_RANDOM && HAVE_DEV_RANDOM + if (has_dev_urandom()) + return get_dev_random_seed(); #endif -#if HAVE_CRYPTGENRANDOM - return get_cryptgenrandom_seed(); +#if defined HAVE_CRYPTGENRANDOM && HAVE_CRYPTGENRANDOM + return get_cryptgenrandom_seed(); #endif - return get_time_seed(); + return get_time_seed(); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/random_seed.h thunderbird-91.8.1+build1/comm/third_party/json-c/random_seed.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/random_seed.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/random_seed.h 2022-04-15 07:49:21.000000000 +0000 @@ -20,7 +20,7 @@ extern "C" { #endif -extern int json_c_get_random_seed(); +extern int json_c_get_random_seed(void); #ifdef __cplusplus } diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/README.html thunderbird-91.8.1+build1/comm/third_party/json-c/README.html --- thunderbird-91.7.0+build2/comm/third_party/json-c/README.html 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/README.html 2022-04-15 07:49:21.000000000 +0000 @@ -8,8 +8,8 @@

JSON-C - A JSON implementation in C

Overview

-

JSON-C implements a reference counting object model that allows you to easily - construct JSON objects in C, output them as JSON formatted strings and parse +

JSON-C implements a reference counting object model that allows you to easily + construct JSON objects in C, output them as JSON formatted strings and parse JSON formatted strings back into the C representation of JSON objects. It aims to conform to RFC 7159.

@@ -26,8 +26,7 @@

Documentation

-

Doxygen generated documentation exists here - and Win32 specific notes can be found here.

+

Doxygen generated documentation exists here.

GIT Reposository

git clone https://github.com/json-c/json-c.git

diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/README.md thunderbird-91.8.1+build1/comm/third_party/json-c/README.md --- thunderbird-91.7.0+build2/comm/third_party/json-c/README.md 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/README.md 2022-04-15 07:49:22.000000000 +0000 @@ -1,12 +1,17 @@ -`json-c` {#mainpage} +\mainpage + +`json-c` ======== 1. [Overview and Build Status](#overview) 2. [Building on Unix](#buildunix) -3. [Install Prerequisites](#installprereq) -4. [Building with partial threading support](#buildthreaded) -5. [Linking to libjson-c](#linking) -6. [Using json-c](#using) + * [Prerequisites](#installprereq) + * [Build commands](#buildcmds) +3. [CMake options](#CMake) +4. [Testing](#testing) +5. [Building with `vcpkg`](#buildvcpkg) +6. [Linking to libjson-c](#linking) +7. [Using json-c](#using) JSON-C - A JSON implementation in C ----------------------------------- @@ -15,126 +20,195 @@ * [AppVeyor Build](https://ci.appveyor.com/project/hawicz/json-c) ![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/json-c/json-c?branch=master&svg=true) * [Travis Build](https://travis-ci.org/json-c/json-c) ![Travis Build Status](https://travis-ci.org/json-c/json-c.svg?branch=master) -JSON-C implements a reference counting object model that allows you to easily -construct JSON objects in C, output them as JSON formatted strings and parse +Test Status +* [Coveralls](https://coveralls.io/github/json-c/json-c?branch=master) [![Coverage Status](https://coveralls.io/repos/github/json-c/json-c/badge.svg?branch=master)](https://coveralls.io/github/json-c/json-c?branch=master) + +JSON-C implements a reference counting object model that allows you to easily +construct JSON objects in C, output them as JSON formatted strings and parse JSON formatted strings back into the C representation of JSON objects. It aims to conform to [RFC 7159](https://tools.ietf.org/html/rfc7159). - -Building on Unix with `git`, `gcc` and `autotools` +Building on Unix with `git`, `gcc` and `cmake` -------------------------------------------------- Home page for json-c: https://github.com/json-c/json-c/wiki -### Prerequisites: - -See also the "Installing prerequisites" section below. +### Prerequisites: - `gcc`, `clang`, or another C compiler - - `libtool>=2.2.6b` -If you're not using a release tarball, you'll also need: + - cmake>=2.8, >=3.16 recommended - - `autoconf>=2.64` (`autoreconf`) - - `automake>=1.13` +To generate docs you'll also need: + - `doxygen>=1.8.13` -Make sure you have a complete `libtool` install, including `libtoolize`. +If you are on a relatively modern system, you'll likely be able to install +the prerequisites using your OS's packaging system. -To generate docs (e.g. as part of make distcheck) you'll also need: - - `doxygen>=1.8.13` +### Install using apt (e.g. Ubuntu 16.04.2 LTS) +```sh +sudo apt install git +sudo apt install cmake +sudo apt install doxygen # optional +sudo apt install valgrind # optional +``` -### Build instructions: +### Build instructions: `json-c` GitHub repo: https://github.com/json-c/json-c ```sh $ git clone https://github.com/json-c/json-c.git -$ cd json-c -$ sh autogen.sh +$ mkdir json-c-build +$ cd json-c-build +$ cmake ../json-c # See CMake section below for custom arguments ``` -followed by +Note: it's also possible to put your build directory inside the json-c +source directory, or even not use a separate build directory at all, but +certain things might not work quite right (notably, `make distcheck`) + +Then: ```sh -$ ./configure # --enable-threading $ make +$ make test +$ make USE_VALGRIND=0 test # optionally skip using valgrind $ make install ``` -To build and run the test programs: -```sh -$ make check -$ make USE_VALGRIND=0 check # optionally skip using valgrind -``` - -Install prerequisites ------------------------ +### Generating documentation with Doxygen: -If you are on a relatively modern system, you'll likely be able to install -the prerequisites using your OS's packaging system. +The libray documentation can be generated directly from the source codes using Doxygen tool: -### Install using apt (e.g. Ubuntu 16.04.2 LTS) ```sh -sudo apt install git -sudo apt install autoconf automake libtool -sudo apt install valgrind # optional +# in build directory +make doc +google-chrome doc/html/index.html ``` -Then start from the "git clone" command, above. -### Manually install and build autoconf, automake and libtool +CMake Options +-------------------- -For older OS's that don't have up-to-date version of the packages will -require a bit more work. For example, CentOS release 5.11, etc... +The json-c library is built with [CMake](https://cmake.org/cmake-tutorial/), +which can take a few options. -```sh -curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz -curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz -curl -O http://ftp.gnu.org/gnu/libtool/libtool-2.2.6b.tar.gz +Variable | Type | Description +-----------------------------|--------|-------------- +CMAKE_INSTALL_PREFIX | String | The install location. +CMAKE_BUILD_TYPE | String | Defaults to "debug". +BUILD_SHARED_LIBS | Bool | The default build generates a dynamic (dll/so) library. Set this to OFF to create a static library only. +BUILD_STATIC_LIBS | Bool | The default build generates a static (lib/a) library. Set this to OFF to create a shared library only. +DISABLE_STATIC_FPIC | Bool | The default builds position independent code. Set this to OFF to create a shared library only. +DISABLE_BSYMBOLIC | Bool | Disable use of -Bsymbolic-functions. +DISABLE_THREAD_LOCAL_STORAGE | Bool | Disable use of Thread-Local Storage (HAVE___THREAD). +DISABLE_WERROR | Bool | Disable use of -Werror. +ENABLE_RDRAND | Bool | Enable RDRAND Hardware RNG Hash Seed. +ENABLE_THREADING | Bool | Enable partial threading support. +OVERRIDE_GET_RANDOM_SEED | String | A block of code to use instead of the default implementation of json_c_get_random_seed(), e.g. on embedded platforms where not even the fallback to time() works. Must be a single line. -tar xzf autoconf-2.69.tar.gz -tar xzf automake-1.15.tar.gz -tar xzf libtool-2.2.6b.tar.gz +Pass these options as `-D` on CMake's command-line. -export PATH=${HOME}/ac_install/bin:$PATH - -(cd autoconf-2.69 && \ - ./configure --prefix ${HOME}/ac_install && \ - make && \ - make install) - -(cd automake-1.15 && \ - ./configure --prefix ${HOME}/ac_install && \ - make && \ - make install) - -(cd libtool-2.2.6b && \ - ./configure --prefix ${HOME}/ac_install && \ - make && \ - make install) +```sh +# build a static library only +cmake -DBUILD_SHARED_LIBS=OFF .. ``` - -Building with partial threading support ----------------------------------------- +### Building with partial threading support Although json-c does not support fully multi-threaded access to -object trees, it has some code to help make use in threaded programs +object trees, it has some code to help make its use in threaded programs a bit safer. Currently, this is limited to using atomic operations for json_object_get() and json_object_put(). Since this may have a performance impact, of at least 3x slower according to https://stackoverflow.com/a/11609063, it is disabled by -default. You may turn it on by adjusting your configure command with: - --enable-threading +default. You may turn it on by adjusting your cmake command with: + -DENABLE_THREADING=ON Separately, the default hash function used for object field keys, -lh_char_hash, uses a compare-and-swap operation to ensure the randomly +lh_char_hash, uses a compare-and-swap operation to ensure the random seed is only generated once. Because this is a one-time operation, it is always compiled in when the compare-and-swap operation is available. +### cmake-configure wrapper script + +For those familiar with the old autoconf/autogen.sh/configure method, +there is a `cmake-configure` wrapper script to ease the transition to cmake. + +```sh +mkdir build +cd build +../cmake-configure --prefix=/some/install/path +make +``` + +cmake-configure can take a few options. + +| options | Description| +| ---- | ---- | +| prefix=PREFIX | install architecture-independent files in PREFIX | +| enable-threading | Enable code to support partly multi-threaded use | +| enable-rdrand | Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms. | +| enable-shared | build shared libraries [default=yes] | +| enable-static | build static libraries [default=yes] | +| disable-Bsymbolic | Avoid linking with -Bsymbolic-function | +| disable-werror | Avoid treating compiler warnings as fatal errors | + + +Testing: +---------- + +By default, if valgrind is available running tests uses it. +That can slow the tests down considerably, so to disable it use: +```sh +export USE_VALGRIND=0 +``` + +To run tests a separate build directory is recommended: +```sh +mkdir build-test +cd build-test +# VALGRIND=1 causes -DVALGRIND=1 to be passed when compiling code +# which uses slightly slower, but valgrind-safe code. +VALGRIND=1 cmake .. +make + +make test +# By default, if valgrind is available running tests uses it. +make USE_VALGRIND=0 test # optionally skip using valgrind +``` + +If a test fails, check `Testing/Temporary/LastTest.log`, +`tests/testSubDir/${testname}/${testname}.vg.out`, and other similar files. +If there is insufficient output try: +```sh +VERBOSE=1 make test +``` +or +```sh +JSONC_TEST_TRACE=1 make test +``` +and check the log files again. + + +Building on Unix and Windows with `vcpkg` +-------------------------------------------------- + +You can download and install JSON-C using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + vcpkg install json-c + +The JSON-C port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + + Linking to `libjson-c` ---------------------- @@ -165,9 +239,38 @@ * json_tokener.h - Methods for parsing and serializing json-c object trees. * json_pointer.h - JSON Pointer (RFC 6901) implementation for retrieving objects from a json-c object tree. -* json_object_iterator.h - Methods for iterating over single json_object instances. +* json_object_iterator.h - Methods for iterating over single json_object instances. (See also `json_object_object_foreach()` in json_object.h) * json_visit.h - Methods for walking a tree of json-c objects. * json_util.h - Miscelleanous utility functions. -For a full list of headers see [files.html](files.html) +For a full list of headers see [files.html](http://json-c.github.io/json-c/json-c-current-release/doc/html/files.html) + +The primary type in json-c is json_object. It describes a reference counted +tree of json objects which are created by either parsing text with a +json_tokener (i.e. `json_tokener_parse_ex()`), or by creating +(with `json_object_new_object()`, `json_object_new_int()`, etc...) and adding +(with `json_object_object_add()`, `json_object_array_add()`, etc...) them +individually. +Typically, every object in the tree will have one reference, from it's parent. +When you are done with the tree of objects, you call json_object_put() on just +the root object to free it, which recurses down through any child objects +calling json_object_put() on each one of those in turn. + +You can get a reference to a single child +(`json_object_object_get()` or `json_object_array_get_idx()`) +and use that object as long as its parent is valid. +If you need a child object to live longer than its parent, you can +increment the child's refcount (`json_object_get()`) to allow it to survive +the parent being freed or it being removed from its parent +(`json_object_object_del()` or `json_object_array_del_idx()`) + +When parsing text, the json_tokener object is independent from the json_object +that it returns. It can be allocated (`json_tokener_new()`) +used ones or multiple times (`json_tokener_parse_ex()`, and +freed (`json_tokener_free()`) while the json_object objects live on. + +A json_object tree can be serialized back into a string with +`json_object_to_json_string_ext()`. The string that is returned +is only valid until the next "to_json_string" call on that same object. +Also, it is freed when the json_object is freed. diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/RELEASE_CHECKLIST.txt thunderbird-91.8.1+build1/comm/third_party/json-c/RELEASE_CHECKLIST.txt --- thunderbird-91.7.0+build2/comm/third_party/json-c/RELEASE_CHECKLIST.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/RELEASE_CHECKLIST.txt 2022-04-15 07:49:21.000000000 +0000 @@ -1,73 +1,103 @@ -Release checklist: +# Release checklist: + +## Pre-release tasks + +* Figure out whether a release is worthwhile to do. +* Analyze the previous release branch to see if anything should have been + applied to master. +* Collect changes and assemble tentative release notes. + * Identify previous release branch point + * Check commit logs between previous branch point and now for + notable changes worth mentioning + * Create a new issues_closed_for_X.Y.md file + * Include notable entries from here in the release notes. + * Analyze APIs between previous release branch and master to produce list of + changes (added/removed/updated funcs, etc...), and detect backwards compat + issues. + * https://github.com/lvc/abi-compliance-checker + * If the new release is not backwards compatible, then this is a MAJOR release. + * Mention removed features in ChangeLog + * Consider re-adding backwards compatible support, through symbol + aliases and appropriate entries in json-c.sym + * Update the AUTHORS file + * Exclude mentioning changes that have already been included in a point + release of the previous release branch. + +* Update ChangeLog with relevant notes before branching. + +* Check that the compile works on Linux - automatic through Travis +* Check that the compile works on NetBSD +* Check that the compile works on Windows - automatic through AppVeyor + +## Release creation + +Start creating the new release: + release=0.15 + git clone https://github.com/json-c/json-c json-c-${release} + + mkdir distcheck + cd distcheck + # Note, the build directory *must* be entirely separate from + # the source tree for distcheck to work properly. + cmake ../json-c-${release} + make distcheck + cd .. -release=0.13 -git clone https://github.com/json-c/json-c json-c-${release} -cd json-c-${release} - -Check that the compile works on Linux -Check that the compile works on NetBSD -Check that the compile works on Windows -Run "make distcheck" and fix any problems - (e.g. adding new files to SOURCES variables in Makefile.am) -Check ChangeLog to see if anything should be added. Make any fixes/changes *before* branching. - git branch json-c-${release} - git checkout json-c-${release} + cd json-c-${release} + git branch json-c-${release} + git checkout json-c-${release} ------------ -Update the version in json_c_version.h -Update the version in Doxyfile -Update the version in configure.ac -Update the version in CMakeLists.txt - Use ${release}. +Using ${release}: + Update the version in json_c_version.h + Update the version in CMakeLists.txt (VERSION in the project(...) line) + Update the version in config.h.win32 (several places) -Update the libjson_la_LDFLAGS line in Makefile.am to the new version. - Generally, unless we're doing a major release, change: - -version-info x:y:z - to - -version-info x:y+1:z - ------------- +Update the set_target_properties() line in CmakeLists.txt to set the shared +library version. Generally, unless we're doing a major release, change: + VERSION x.y.z +to + VERSION x.y+1.z -Generate the configure script and other files: - sh autogen.sh - git add -f Makefile.in aclocal.m4 config.guess config.h.in \ - config.sub configure depcomp install-sh \ - ltmain.sh missing tests/Makefile.in \ - INSTALL + git commit -a -m "Bump version to ${release}" - # check for anything else to be added: - git status --ignored - git commit +If we're doing a major release (SONAME bump), also bump the version + of ALL symbols in json-c.sym. + See explanation at https://github.com/json-c/json-c/issues/621 + More info at: https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf ------------ Generate the doxygen documentation: - doxygen - git add -f doc - git commit doc + + doxygen + git add -f doc + git commit doc ------------ -cd .. -echo .git > excludes -echo autom4te.cache >> excludes -tar -czf json-c-${release}.tar.gz -X excludes json-c-${release} +Create the release tarballs: + + cd .. + echo .git > excludes + tar -czf json-c-${release}.tar.gz -X excludes json-c-${release} -echo doc >> excludes -tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release} + echo doc >> excludes + tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release} ------------ Tag the branch: -cd json-c-${release} -git tag -a json-c-${release}-$(date +%Y%m%d) -m "Release json-c-${release}" -git push origin json-c-${release} -git push --tags + cd json-c-${release} + git tag -a json-c-${release}-$(date +%Y%m%d) -m "Release json-c-${release}" + + git push origin json-c-${release} + git push --tags ------------ @@ -75,7 +105,7 @@ https://console.aws.amazon.com/s3/ Upload the two tarballs in the json-c_releases folder. - When uploading, use "Reduced Redundancy", and make the uploaded files publicly accessible. + When uploading, use "Standard" storage class, and make the uploaded files publicly accessible. Logout of Amazon S3, and verify that the files are visible. https://s3.amazonaws.com/json-c_releases/releases/index.html @@ -84,48 +114,51 @@ Post-release checklist: -git checkout master -Add new section to ChangeLog -Update the version in json_c_version.h -Update the version in Doxyfile -Update the version in configure.ac -Update the version in CMakeLists.txt - Use ${release}.99 to indicate a version "newer" than anything on the branch. - -Leave the libjson_la_LDFLAGS line in Makefile.am alone. - For more details see: - http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html + git checkout master + +Add new section to ChangeLog for ${release}+1 + +Use ${release}.99 to indicate a version "newer" than anything on the branch: + Update the version in json_c_version.h + Update the version in CMakeLists.txt + Update the version in config.h.win32 + +Update RELEASE_CHECKLIST.txt, set release=${release}+1 + +Update the set_target_properties() line in CmakeLists.txt to match the release branch. + + git commit -a -m "Update the master branch to version 0.${release}.99" + git push ------------ Update the gh-pages branch with new docs: -cd json-c-${release} -git checkout json-c-${release} -cd .. - -git clone -b gh-pages https://github.com/json-c/json-c json-c-pages -cd json-c-pages -mkdir json-c-${release} -cp -R ../json-c-${release}/doc json-c-${release}/. -cp ../json-c-${release}/README-WIN32.html json-c-${release}/. -git add json-c-${release} -git commit + cd json-c-${release} + git checkout json-c-${release} + cd .. + + git clone -b gh-pages https://github.com/json-c/json-c json-c-pages + cd json-c-pages + mkdir json-c-${release} + cp -R ../json-c-${release}/doc json-c-${release}/. + git add json-c-${release} + git commit -a -m "Add the ${release} docs." -vi index.html - Add/change links to current release. + vi index.html + # Add/change links to current release. -git commit index.html + git commit -a -m "Update the doc links to point at ${release}" -git push + git push ------------ Update checksums on wiki page. -cd .. -openssl sha -sha256 json-c*gz -openssl md5 json-c*gz + cd .. + openssl sha -sha256 json-c*gz + openssl md5 json-c*gz Copy and paste this output into the wiki page at: https://github.com/json-c/json-c/wiki @@ -133,4 +166,3 @@ ------------ Send an email to the mailing list. - diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/snprintf_compat.h thunderbird-91.8.1+build1/comm/third_party/json-c/snprintf_compat.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/snprintf_compat.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/snprintf_compat.h 2022-04-15 07:49:21.000000000 +0000 @@ -13,7 +13,7 @@ #include -#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER) +#if !defined(HAVE_SNPRINTF) && (defined(_MSC_VER) || defined(__MINGW32__)) static int json_c_vsnprintf(char *str, size_t size, const char *format, va_list ap) { int ret; @@ -35,7 +35,7 @@ #define snprintf json_c_snprintf #elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */ -# error Need vsnprintf! +#error Need vsnprintf! #endif /* !HAVE_SNPRINTF && defined(WIN32) */ #endif /* __snprintf_compat_h */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/strdup_compat.h thunderbird-91.8.1+build1/comm/third_party/json-c/strdup_compat.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/strdup_compat.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/strdup_compat.h 2022-04-15 07:49:22.000000000 +0000 @@ -7,10 +7,10 @@ */ #if !defined(HAVE_STRDUP) && defined(_MSC_VER) - /* MSC has the version as _strdup */ -# define strdup _strdup +/* MSC has the version as _strdup */ +#define strdup _strdup #elif !defined(HAVE_STRDUP) -# error You do not have strdup on your system. +#error You do not have strdup on your system. #endif /* HAVE_STRDUP */ #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/strerror_override.c thunderbird-91.8.1+build1/comm/third_party/json-c/strerror_override.c --- thunderbird-91.7.0+build2/comm/third_party/json-c/strerror_override.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/strerror_override.c 2022-04-15 07:49:21.000000000 +0000 @@ -5,10 +5,12 @@ * Override strerror() to get consistent output across platforms. */ -static struct { +static struct +{ int errno_value; const char *errno_str; } errno_list[] = { +/* clang-format off */ #define STRINGIFY(x) #x #define ENTRY(x) {x, &STRINGIFY(undef_ ## x)[6]} ENTRY(EPERM), @@ -18,7 +20,9 @@ ENTRY(EIO), ENTRY(ENXIO), ENTRY(E2BIG), +#ifdef ENOEXEC ENTRY(ENOEXEC), +#endif ENTRY(EBADF), ENTRY(ECHILD), ENTRY(EDEADLK), @@ -52,9 +56,11 @@ ENTRY(EAGAIN), { 0, (char *)0 } }; +/* clang-format on */ // Enabled during tests -int _json_c_strerror_enable = 0; +static int _json_c_strerror_enable = 0; +extern char *getenv(const char *name); // Avoid including stdlib.h #define PREFIX "ERRNO=" static char errno_buf[128] = PREFIX; @@ -65,6 +71,8 @@ int ii, jj; if (!_json_c_strerror_enable) + _json_c_strerror_enable = (getenv("_JSON_C_STRERROR_ENABLE") == NULL) ? -1 : 1; + if (_json_c_strerror_enable == -1) return strerror(errno_in); // Avoid standard functions, so we don't need to include any @@ -76,7 +84,8 @@ if (errno_list[ii].errno_value != errno_in) continue; - for (start_idx = sizeof(PREFIX) - 1, jj = 0; errno_str[jj] != '\0'; jj++, start_idx++) + for (start_idx = sizeof(PREFIX) - 1, jj = 0; errno_str[jj] != '\0'; + jj++, start_idx++) { errno_buf[start_idx] = errno_str[jj]; } @@ -92,10 +101,9 @@ digbuf[ii] = "0123456789"[(errno_in % 10)]; // Reverse the digits - for (start_idx = sizeof(PREFIX) - 1 ; ii >= 0; ii--, start_idx++) + for (start_idx = sizeof(PREFIX) - 1; ii >= 0; ii--, start_idx++) { errno_buf[start_idx] = digbuf[ii]; } return errno_buf; } - diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/strerror_override.h thunderbird-91.8.1+build1/comm/third_party/json-c/strerror_override.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/strerror_override.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/strerror_override.h 2022-04-15 07:49:21.000000000 +0000 @@ -20,11 +20,11 @@ JSON_EXPORT char *_json_c_strerror(int errno_in); #ifndef STRERROR_OVERRIDE_IMPL -#define strerror _json_c_strerror +#define strerror _json_c_strerror #endif #ifdef __cplusplus } #endif -#endif /* _json_strerror_override_h_ */ +#endif /* _json_strerror_override_h_ */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/strerror_override_private.h thunderbird-91.8.1+build1/comm/third_party/json-c/strerror_override_private.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/strerror_override_private.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/strerror_override_private.h 2022-04-15 07:49:21.000000000 +0000 @@ -6,7 +6,9 @@ * @brief Do not use, json-c internal, may be changed or removed at any time. */ +#include "json_types.h" + /* Used by tests to get consistent output */ -extern int _json_c_strerror_enable; +JSON_EXPORT int _json_c_strerror_enable; #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/STYLE.txt thunderbird-91.8.1+build1/comm/third_party/json-c/STYLE.txt --- thunderbird-91.7.0+build2/comm/third_party/json-c/STYLE.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/STYLE.txt 2022-04-15 07:49:21.000000000 +0000 @@ -4,22 +4,22 @@ For new code and major changes to a function, switch to the official json-c style. Official json-c style: + Aim for readability, not strict conformance to fixed style rules. -These rules are not comprehensive. Look to existing code for guidelines. -Indentation is tab based, with continuations of long lines starting with tabs then spaces for alignment. -Try to line up components of continuation lines with corresponding part of the line above (i.e. "indent -lp" effect), but avoid excessive identation tha causes extra line wraps. - e.g. (T=tab, S=space): -TTTTsome_long_func_call(arg1, arg2, -TTTTSSSSSSSSSSSSSSSSSSSarg3, arg4); -TTTTsome_reallly_really_long_func_name(arg1, -TTTTTarg2, arg3, arg4); -There should be a space between "if"/"while" and the following parenthesis. -"case" lines are indented at the same level as the "switch" statement. -Commas are followed by a single space. -Include spaces around most non-unary, non-postfix operators, "=", "==', "&", "||", etc... -Function calls have no space between the name and the parenthesis. -Curly braces go on their own line. -Curly braces may be omitted. +Formatting is tab based; previous attempts at proper alignment with +spaces for continuation lines have been abandoned in favor of the +convenience of using clang-format. +Refer to the .clang-format file for details, and run the tool before commit: + + clang-format -i somefile.c foo.h + +For sections of code that would be significantly negatively impacted, surround +them with magic comments to disable formatting: + + /* clang-format off */ + ...code... + /* clang-format on */ + Naming: Words within function and variable names are separated with underscores. Avoid camel case. diff -Nru thunderbird-91.7.0+build2/comm/third_party/json-c/vasprintf_compat.h thunderbird-91.8.1+build1/comm/third_party/json-c/vasprintf_compat.h --- thunderbird-91.7.0+build2/comm/third_party/json-c/vasprintf_compat.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/json-c/vasprintf_compat.h 2022-04-15 07:49:21.000000000 +0000 @@ -8,6 +8,8 @@ #include "snprintf_compat.h" +#include + #if !defined(HAVE_VASPRINTF) /* CAW: compliant version of vasprintf */ static int vasprintf(char **buf, const char *fmt, va_list ap) @@ -18,24 +20,36 @@ int chars; char *b; - if(!buf) { return -1; } + if (!buf) + { + return -1; + } #ifdef WIN32 - chars = _vscprintf(fmt, ap)+1; -#else /* !defined(WIN32) */ + chars = _vscprintf(fmt, ap) + 1; +#else /* !defined(WIN32) */ /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite - our buffer like on some 64bit sun systems.... but hey, its time to move on */ - chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; - if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ + * our buffer like on some 64bit sun systems.... but hey, its time to move on + */ + chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap) + 1; + if (chars < 0) + { + chars *= -1; + } /* CAW: old glibc versions have this problem */ #endif /* defined(WIN32) */ - b = (char*)malloc(sizeof(char)*chars); - if(!b) { return -1; } + b = (char *)malloc(sizeof(char) * chars); + if (!b) + { + return -1; + } - if((chars = vsprintf(b, fmt, ap)) < 0) + if ((chars = vsprintf(b, fmt, ap)) < 0) { free(b); - } else { + } + else + { *buf = b; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/openpgp.configure thunderbird-91.8.1+build1/comm/third_party/openpgp.configure --- thunderbird-91.7.0+build2/comm/third_party/openpgp.configure 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/openpgp.configure 2022-04-15 07:49:21.000000000 +0000 @@ -277,27 +277,3 @@ set_config("COMPILER_RT_BUILTIN_PATH", clang_rt_builtins.clang_rt_path, when=is_windows) set_config("COMPILER_RT_BUILTIN_LIB", clang_rt_builtins.clang_rt_lib, when=is_windows) - - -@depends(c_compiler, cxx_compiler, when=compile_environment) -def rnp_compiler(c_compiler, cxx_compiler): - # Replace -std=gnu++17 or -std=c++17 with -std=gnu++11 or -std=c++11 - _cxxflags = [] - for f in cxx_compiler.flags: - if f == "-std=c++17": - _cxxflags.append("-std=c++14") - elif f == "-std=gnu++17": - _cxxflags.append("-std=gnu++11") - else: - _cxxflags.append(f) - - rnp_cc = " ".join( - list(c_compiler.wrapper) + [c_compiler.compiler] + c_compiler.flags - ) - rnp_cxx = " ".join(list(cxx_compiler.wrapper) + [cxx_compiler.compiler] + _cxxflags) - - return namespace(rnp_cc=rnp_cc, rnp_cxx=rnp_cxx) - - -set_config("MZLA_RNP_CC", rnp_compiler.rnp_cc) -set_config("MZLA_RNP_CXX", rnp_compiler.rnp_cxx) diff -Nru thunderbird-91.7.0+build2/comm/third_party/patches/rnp/disable_obsolete_ciphers.patch thunderbird-91.8.1+build1/comm/third_party/patches/rnp/disable_obsolete_ciphers.patch --- thunderbird-91.7.0+build2/comm/third_party/patches/rnp/disable_obsolete_ciphers.patch 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/patches/rnp/disable_obsolete_ciphers.patch 2022-04-15 07:49:21.000000000 +0000 @@ -1,12 +1,12 @@ diff --git a/third_party/rnp/src/lib/crypto/signatures.cpp b/third_party/rnp/src/lib/crypto/signatures.cpp --- a/third_party/rnp/src/lib/crypto/signatures.cpp +++ b/third_party/rnp/src/lib/crypto/signatures.cpp -@@ -188,29 +188,89 @@ signature_calculate(pgp_signature_t * - sig->write_material(material); - return RNP_SUCCESS; +@@ -178,22 +178,83 @@ signature_calculate(pgp_signature_t & + try { + sig.write_material(material); } catch (const std::exception &e) { RNP_LOG("%s", e.what()); - return RNP_ERROR_GENERIC; + throw; } } @@ -64,30 +64,24 @@ +} + rnp_result_t - signature_validate(const pgp_signature_t *sig, const pgp_key_material_t *key, pgp_hash_t *hash) + signature_validate(const pgp_signature_t & sig, + const pgp_key_material_t & key, + rnp::Hash & hash, + const rnp::SecurityContext &ctx) { - uint8_t hval[PGP_MAX_HASH_SIZE]; - size_t hlen = 0; - rnp_result_t ret = RNP_ERROR_GENERIC; - - const pgp_hash_alg_t hash_alg = pgp_hash_alg_type(hash); -+ if (!is_hash_alg_allowed_in_sig(hash_alg)) { ++ if (!is_hash_alg_allowed_in_sig(hash.alg())) { + return RNP_ERROR_SIGNATURE_INVALID; + } - - if (!key) { - return RNP_ERROR_NULL_POINTER; - } - -+ if (!is_pubkey_alg_allowed_in_sig(sig->palg)) { ++ ++ if (!is_pubkey_alg_allowed_in_sig(sig.palg)) { + return RNP_ERROR_SIGNATURE_INVALID; + } + - if (sig->palg != key->alg) { + if (sig.palg != key.alg) { RNP_LOG("Signature and key do not agree on algorithm type: %d vs %d", - (int) sig->palg, - (int) key->alg); + (int) sig.palg, + (int) key.alg); return RNP_ERROR_BAD_PARAMETERS; } - /* Finalize hash */ + /* Check signature security */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/README.json-c thunderbird-91.8.1+build1/comm/third_party/README.json-c --- thunderbird-91.7.0+build2/comm/third_party/README.json-c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/README.json-c 2022-04-15 07:49:21.000000000 +0000 @@ -1,41 +1,33 @@ -Directory ./json-c contains a copy of version 0.13.1 of the json-c library, -which has been obtained from https://s3.amazonaws.com/json-c_releases/releases/json-c-0.13.1-nodoc.tar.gz . +Directory ./json-c contains a copy of version 0.15 of the json-c library, +which has been obtained from https://s3.amazonaws.com/json-c_releases/releases/json-c-0.15-nodoc.tar.gz . (Link at https://github.com/json-c/json-c/wiki). For licensing information, please refer to the included documentation. The SHA256SUM of the imported file is: -94a26340c0785fcff4f46ff38609cf84ebcd670df0c8efd75d039cc951d80132 json-c-0.13.1-nodoc.tar.gz +99bca4f944b8ced8ae0bbc6310d6a3528ca715e69541793a1ef51f8c5b4b0878 json-c-0.15-nodoc.tar.gz The following files and directories were removed from the source distribution's root: -autoconf-archive/ +.github/ +apps/ +bench/ +cmake/ fuzz/ tests/ +.clang-format .editorconfig .gitignore .travis.yml Android.configure.mk CMakeLists.txt -Doxyfile -Makefile.am -Makefile.in README -aclocal.m4 appveyor.yml -autogen.sh -compile -config.guess -config.sub -configure -configure.ac -depcomp -install-sh -json-c-uninstalled.pc.in +cmake-configure json-c.pc.in -ltmain.sh -missing -test-driver +json-c.sym The following files were added to the source's root by MZLA Technologies: +config.h.in (modified copy from cmake/config.h.in) moz.build + diff -Nru thunderbird-91.7.0+build2/comm/third_party/README.rnp thunderbird-91.8.1+build1/comm/third_party/README.rnp --- thunderbird-91.7.0+build2/comm/third_party/README.rnp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/README.rnp 2022-04-15 07:49:21.000000000 +0000 @@ -1,7 +1,7 @@ Directory ./rnp contains a copy of rnp which has been obtained from: https://github.com/rnpgp/rnp -[commit dd923a4e1375a01cf3e8dab7b97be96dde9f94b3] +[commit f06439f77e50974e427023f77a459843e46ac682] For licensing information, please refer to the included documentation. diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/CHANGELOG.md thunderbird-91.8.1+build1/comm/third_party/rnp/CHANGELOG.md --- thunderbird-91.7.0+build2/comm/third_party/rnp/CHANGELOG.md 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/CHANGELOG.md 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,52 @@ ## Changelog +### 0.16.0 [2022-01-20] + +#### General + +* Added support for OpenSSL cryptography backend so RNP may be built and used on systems without the Botan installed. +* Added compile-time switches to disable certain features (AEAD, Brainpool curves, SM2/SM3/SM4 algorithms, Twofish) +* Fixed possible incompatibility with GnuPG on x25519 secret key export from RNP to GnuPG. +* Fixed building if Git is not available. +* Fixed export of non-FFI symbols from the rnp.so/rnp.dylib. +* Fixed support for Gnu/Hurd (absence of PATH_MAX). +* Added support for `None` compression algorithm. +* Added support for the dumping of notation data signature subpackets. +* Fixed key expiration time calculation in the case with newer non-primary self-certification. +* Improved performance of key import (no key material checks) + +#### Security + +* Added initial support for customizable security profiles. +* Mark SHA1 signatures produced later than 2019-01-19, as invalid. +* Mark MD5 signatures produced later than 2012-01-01, as invalid. +* Remove SHA1 and 3DES from the default key preferences. +* Use SHA1 collision detection code when using SHA1. +* Mark signatures with unknown critical notation as invalid. +* Do not prematurely mark secret keys as valid. +* Validate secret key material before the first operation. +* Limit the number of possible message recipients/signatures to a reasonable value (16k). +* Limit the number of signature subpackets during parsing. + +#### FFI + +* Added functions `rnp_backend_string()` and `rnp_backend_version()`. +* Added functions `rnp_key_25519_bits_tweaked()` and `rnp_key_25519_bits_tweak()` to check and fix x25519 secret key bits. +* Added security profile manipulation functions: `rnp_add_security_rule()`, `rnp_get_security_rule()`, `rnp_remove_security_rule()`. +* Added function `rnp_signature_get_expiration()`. +* Deprecate functions `rnp_enable_debug()`/`rnp_disable_debug()`. + +#### CLI + +* Write new detailed help messages for `rnp` and `rnpkeys`. +* Added `-` (stdin) and `env:VAR_NAME` input specifiers, as well as `-` (stdout) output specifier. +* Do not fail with empty keyrings if those are not needed for the operation. +* Added algorithm aliases for better usability (i.e. `SHA-256`, `SHA256`, etc.). +* Added option `--notty` to print everything to stdout instead of TTY. +* Added command `--edit-key` with subcommands `--check-cv25519-bits` and `--fix-cv25519-bits`. +* Remove support for `-o someoption=somevalue`, which is unused. +* Remove no longer used support for additional debug dumping via `--debug source.c`. + ### 0.15.2 [2021-07-20] #### General @@ -32,7 +79,7 @@ #### FFI * Added function `rnp_key_valid_till64()` to correctly handle keys which expire after the year 2038. -* Added RNP_FEATURE_* defines to be used instead of raw strings. +* Added `RNP_FEATURE_*` defines to be used instead of raw strings. #### Security @@ -281,7 +328,7 @@ #### FFI -* Fixed rnp_op_add_signature for G10 keys +* Fixed `rnp_op_add_signature` for G10 keys ### 0.9.1 [2018-07-12] @@ -292,7 +339,7 @@ #### CLI * Added support for keyid/fpr usage with (some) spaces and 0x prefix in - operations (--sign, etc). + operations (`--sign`, etc). #### FFI diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/default.nix thunderbird-91.8.1+build1/comm/third_party/rnp/default.nix --- thunderbird-91.7.0+build2/comm/third_party/rnp/default.nix 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/default.nix 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,46 @@ +{ pkgs ? import { } +, lib ? pkgs.lib +, stdenv ? pkgs.stdenv +}: + +stdenv.mkDerivation rec { + pname = "rnp"; + version = "unstable"; + + src = ./.; + + buildInputs = with pkgs; [ zlib bzip2 json_c botan2 ]; + + cmakeFlags = [ + "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}" + "-DBUILD_SHARED_LIBS=on" + "-DBUILD_TESTING=on" + "-DDOWNLOAD_GTEST=off" + "-DDOWNLOAD_RUBYRNP=off" + ]; + + nativeBuildInputs = with pkgs; [ asciidoctor cmake gnupg gtest pkg-config python3 ]; + + # NOTE: check-only inputs should ideally be moved to checkInputs, but it + # would fail during buildPhase. + # checkInputs = [ gtest python3 ]; + + outputs = [ "out" "lib" "dev" ]; + + preConfigure = '' + commitEpoch=$(date +%s) + baseVersion=$(cat version.txt) + echo "v$baseVersion-0-g0-dirty+$commitEpoch" > version.txt + + # For generating the correct timestamp in cmake + export SOURCE_DATE_EPOCH=$commitEpoch + ''; + + meta = with lib; { + homepage = "https://github.com/rnpgp/rnp"; + description = "High performance C++ OpenPGP library, fully compliant to RFC 4880"; + license = licenses.bsd2; + platforms = platforms.all; + maintainers = with maintainers; [ ribose-jeffreylau ]; + }; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/docs/c-usage.adoc thunderbird-91.8.1+build1/comm/third_party/rnp/docs/c-usage.adoc --- thunderbird-91.7.0+build2/comm/third_party/rnp/docs/c-usage.adoc 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/docs/c-usage.adoc 2022-04-15 07:49:21.000000000 +0000 @@ -108,7 +108,7 @@ === verify.c -Location: https://github.com/rnpgp/rnp/blob/master/src/examples/verify.c[ +Location: https://github.com/rnpgp/rnp/blob/master/src/examples/verify.c This example uses keyrings generated in the `generate.c` example. @@ -120,7 +120,7 @@ === dump.c -Location: https://github.com/rnpgp/rnp/blob/master/src/examples/dump.c[ +Location: https://github.com/rnpgp/rnp/blob/master/src/examples/dump.c This example dumps OpenPGP packet information from the input stream (via `stdin` or filename), tuned with flags passed via the diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/docs/installation.adoc thunderbird-91.8.1+build1/comm/third_party/rnp/docs/installation.adoc --- thunderbird-91.7.0+build2/comm/third_party/rnp/docs/installation.adoc 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/docs/installation.adoc 2022-04-15 07:49:22.000000000 +0000 @@ -5,6 +5,26 @@ * `rnp` * `rnpkeys` + +== On NixOS or Nix package manager + +We provide a Nix package for easy installation on NixOS and any OS with Nix +installed (including Linux and macOS, even NixOS on WSL). + +[source,console] +---- +nix-env -iA nixpkgs.rnp +---- + +== With Nix Flakes + +We provide a Nix flake. + +[source,console] +---- +nix profile install github:rnpgp/rnp +---- + == On macOS using Homebrew We provide a Homebrew tap for easy installation of RNP on macOS. @@ -34,15 +54,15 @@ [source,console] ---- # Clone the repository by version tag (or omit it to get the latest sources) -git clone https://github.com/rnpgp/rnp.git -b v0.15.2 +git clone https://github.com/rnpgp/rnp.git -b v0.16.0 # Install required packages sudo apt install g++-8 cmake libbz2-dev zlib1g-dev libjson-c-dev \ build-essential python-minimal # Download, build and install Botan2 -wget -qO- https://botan.randombit.net/releases/Botan-2.14.0.tar.xz | tar xvJ -cd Botan-2.14.0 +wget -qO- https://botan.randombit.net/releases/Botan-2.18.2.tar.xz | tar xvJ +cd Botan-2.18.2 ./configure.py --prefix=/usr make sudo make install @@ -70,7 +90,7 @@ [source,console] ---- # Clone the repository by version tag (or omit it to get the latest sources) -git clone https://github.com/rnpgp/rnp.git -b v0.15.2 +git clone https://github.com/rnpgp/rnp.git -b v0.16.0 # Enable access to `testing` packages by editing /etc/apt/sources.list # deb http://deb.debian.org/debian testing main @@ -91,6 +111,32 @@ sudo make install ---- +== On Gentoo Linux + +RNP ebuilds are available from an overlay repository named `rnp`. + +=== Using eselect-repository (the current way) + +Prerequisite: ensure `eselect-repository` is installed on your system. + +[source,console] +---- +eselect repository enable rnp +emaint sync -r rnp +emerge -av app-crypt/rnp +---- + +=== Using layman (the old way) + +Prerequisite: ensure `layman` is installed on your system. + +[source,console] +---- +layman -a rnp +layman -s rnp +emerge -av app-crypt/rnp +---- + == Compile from source Clone this repo, or download a release and expand it. @@ -185,4 +231,3 @@ You may check dependencies and their paths via `ntldd.exe` in the MSYS command prompt. - diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/docs/signing-keys.adoc thunderbird-91.8.1+build1/comm/third_party/rnp/docs/signing-keys.adoc --- thunderbird-91.7.0+build2/comm/third_party/rnp/docs/signing-keys.adoc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/docs/signing-keys.adoc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,5 @@ + += PGP keys used for signing source code + +The current OpenPGP key used for signing source code for RNP is hosted at +https://www.rnpgp.org/openpgp_keys/[rnpgp.org^]. diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/flake.lock thunderbird-91.8.1+build1/comm/third_party/rnp/flake.lock --- thunderbird-91.7.0+build2/comm/third_party/rnp/flake.lock 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/flake.lock 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,42 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1640849002, + "narHash": "sha256-XrU11TR+Nz7bm8XLU07uQJAxeH5cKnZhXf0hfZftFqE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d50c9666ca2b96b4488551ec968babe4cc45c52b", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/flake.nix thunderbird-91.8.1+build1/comm/third_party/rnp/flake.nix --- thunderbird-91.7.0+build2/comm/third_party/rnp/flake.nix 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/flake.nix 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,26 @@ +{ + description = "High performance C++ OpenPGP library, fully compliant to RFC 4880"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + thePackage = pkgs.callPackage ./default.nix { }; + in + rec { + defaultApp = flake-utils.lib.mkApp { + drv = defaultPackage; + }; + defaultPackage = thePackage; + devShell = pkgs.mkShell { + buildInputs = [ + thePackage + ]; + }; + }); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/include/rekey/rnp_key_store.h thunderbird-91.8.1+build1/comm/third_party/rnp/include/rekey/rnp_key_store.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/include/rekey/rnp_key_store.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/include/rekey/rnp_key_store.h 2022-04-15 07:49:21.000000000 +0000 @@ -40,75 +40,9 @@ #include #include #include - -typedef enum { - KBX_EMPTY_BLOB = 0, - KBX_HEADER_BLOB = 1, - KBX_PGP_BLOB = 2, - KBX_X509_BLOB = 3 -} kbx_blob_type; - -typedef struct { - uint32_t length; - kbx_blob_type type; - - uint8_t *image; -} kbx_blob_t; - -typedef struct { - kbx_blob_t blob; - uint8_t version; - uint16_t flags; - uint32_t file_created_at; - uint32_t last_maintenance_run; -} kbx_header_blob_t; - -typedef struct { - uint8_t fp[PGP_FINGERPRINT_SIZE]; - uint32_t keyid_offset; - uint16_t flags; -} kbx_pgp_key_t; - -typedef struct { - uint32_t offset; - uint32_t length; - uint16_t flags; - uint8_t validity; -} kbx_pgp_uid_t; - -typedef struct { - uint32_t expired; -} kbx_pgp_sig_t; - -typedef struct { - kbx_blob_t blob; - uint8_t version; - uint16_t flags; - uint32_t keyblock_offset; - uint32_t keyblock_length; - - uint16_t nkeys; - uint16_t keys_len; - list keys; // list of kbx_pgp_key_t - - uint16_t sn_size; - uint8_t *sn; - - uint16_t nuids; - uint16_t uids_len; - list uids; // list of kbx_pgp_uid_t - - uint16_t nsigs; - uint16_t sigs_len; - list sigs; // list of kbx_pgp_sig_t - - uint8_t ownertrust; - uint8_t all_Validity; - - uint32_t recheck_after; - uint32_t latest_timestamp; - uint32_t blob_created_at; -} kbx_pgp_blob_t; +#include +#include "librekey/kbx_blob.hpp" +#include "sec_profile.hpp" /* Key import status. Order of elements is important. */ typedef enum pgp_key_import_status_t { @@ -130,17 +64,20 @@ typedef struct rnp_key_store_t { std::string path; pgp_key_store_format_t format; + rnp::SecurityContext & secctx; bool disable_validation = false; /* do not automatically validate keys, added to this key store */ - std::list keys; - pgp_key_fp_map_t keybyfp; - - list blobs = NULL; // list of kbx_blob_t + std::list keys; + pgp_key_fp_map_t keybyfp; + std::vector> blobs; ~rnp_key_store_t(); - rnp_key_store_t() : path(""), format(PGP_KEY_STORE_UNKNOWN){}; - rnp_key_store_t(pgp_key_store_format_t format, const std::string &path); + rnp_key_store_t(rnp::SecurityContext &ctx) + : path(""), format(PGP_KEY_STORE_UNKNOWN), secctx(ctx){}; + rnp_key_store_t(pgp_key_store_format_t format, + const std::string & path, + rnp::SecurityContext & ctx); /* make sure we use only empty constructor */ rnp_key_store_t(rnp_key_store_t &&src) = delete; rnp_key_store_t &operator=(rnp_key_store_t &&) = delete; @@ -201,15 +138,8 @@ bool rnp_key_store_remove_key(rnp_key_store_t *, const pgp_key_t *, bool); -pgp_key_t *rnp_key_store_get_key_by_id(rnp_key_store_t * keyring, - const pgp_key_id_t &keyid, - pgp_key_t * key); - bool rnp_key_store_get_key_grip(const pgp_key_material_t *, pgp_key_grip_t &grip); -const pgp_key_t *rnp_key_store_get_key_by_grip(const rnp_key_store_t *, - const pgp_key_grip_t &); -pgp_key_t * rnp_key_store_get_key_by_grip(rnp_key_store_t *, const pgp_key_grip_t &); const pgp_key_t *rnp_key_store_get_key_by_fpr(const rnp_key_store_t *, const pgp_fingerprint_t &fpr); pgp_key_t * rnp_key_store_get_key_by_fpr(rnp_key_store_t *, const pgp_fingerprint_t &fpr); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/include/repgp/repgp_def.h thunderbird-91.8.1+build1/comm/third_party/rnp/include/repgp/repgp_def.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/include/repgp/repgp_def.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/include/repgp/repgp_def.h 2022-04-15 07:49:21.000000000 +0000 @@ -31,6 +31,8 @@ #ifndef REPGP_DEF_H_ #define REPGP_DEF_H_ +#include + /************************************/ /* Packet Tags - RFC4880, 4.2 */ /************************************/ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/include/rnp/rnp.h thunderbird-91.8.1+build1/comm/third_party/rnp/include/rnp/rnp.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/include/rnp/rnp.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/include/rnp/rnp.h 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017-2020 Ribose Inc. + * Copyright (c) 2017-2021 Ribose Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,6 +108,19 @@ #define RNP_USER_ATTR (2U) /** + * Predefined feature security levels + */ +#define RNP_SECURITY_PROHIBITED (0U) +#define RNP_SECURITY_INSECURE (1U) +#define RNP_SECURITY_DEFAULT (2U) + +/** + * Flags for feature security rules. + */ +#define RNP_SECURITY_OVERRIDE (1U << 0) +#define RNP_SECURITY_REMOVE_ALL (1U << 16) + +/** * Return a constant string describing the result code */ RNP_API const char *rnp_result_to_string(rnp_result_t result); @@ -165,19 +178,22 @@ **/ RNP_API uint64_t rnp_version_commit_timestamp(); -/** Enable debugging for the specified source file. Use 'all' or NULL as parameter to - * enable debug for all sources. - * Note: this must be only used during development since may print out confidential data. +#ifndef RNP_NO_DEPRECATED +/** @brief This function is deprecated and should not be used anymore. It would just silently + * return RNP_SUCCESS. * * @param file name of the sourcer file. Use 'all' to enable debug for all code. + * */ -RNP_API rnp_result_t rnp_enable_debug(const char *file); +RNP_API RNP_DEPRECATED rnp_result_t rnp_enable_debug(const char *file); /** - * @brief Disable previously enabled debug for all files. + * @brief This function is deprecated and should not be used anymore. It would just silently + * return RNP_SUCCESS. * */ -RNP_API rnp_result_t rnp_disable_debug(); +RNP_API RNP_DEPRECATED rnp_result_t rnp_disable_debug(); +#endif /* * Opaque structures @@ -415,6 +431,100 @@ RNP_API rnp_result_t rnp_supported_features(const char *type, char **result); /** + * @brief Add new security rule to the FFI. Security rules allows to override default algorithm + * security settings by disabling them or marking as insecure. After creation of FFI + * object default rules are added, however caller may add more strict rules or + * completely overwrite rule table by calling rnp_remove_security_rule(). + * Note: key signature validation status is cached, so rules should be changed before + * keyrings are loaded or keyring should be reloaded after updating rules. + * + * @param ffi initialized FFI object. + * @param type type of the feature, cannot be NULL. Currently only RNP_FEATURE_HASH_ALG is + * supported. + * @param name name of the feature, i.e. SHA1, MD5. The same values are used in + * rnp_supports_feature()/rnp_supported_features(). + * @param flags additional flags. Following ones currently supported: + * - RNP_SECURITY_OVERRIDE : override all other rules for the specified feature. + * May be used to temporarily enable or disable some feature value (e.g., to + * enable verification of SHA1 or MD5 signature), and then revert changes via + * rnp_remove_security_rule(). + * @param from timestamp, from when the rule is active. Objects that have creation time (like + * signatures) are matched with the closest rules from the past, unless there is + * a rule with an override flag. For instance, given a single rule with algorithm + * 'MD5', level 'insecure' and timestamp '2012-01-01', all signatures made before + * 2012-01-01 using the MD5 hash algorithm are considered to be at the default + * security level (i.e., valid), whereas all signatures made after 2021-01-01 will + * be marked as 'insecure' (i.e., invalid). + * @param level security level of the rule. Currently the following ones are defined: + * - RNP_SECURITY_PROHIBITED : feature (for instance, MD5 algorithm) is completely + * disabled, so no processing can be done. In terms of signature check, that + * would mean the check will fail right after the hashing begins. + * Note: Currently it works in the same way as RNP_SECURITY_INSECURE. + * - RNP_SECURITY_INSECURE : feature (for instance, SHA1 algorithm) is marked as + * insecure. So even valid signatures, produced later than `from`, will be + * marked as invalid. + * - RNP_SECURITY_DEFAULT : feature is secure enough. Default value when there are + * no other rules for feature. + * + * @return RNP_SUCCESS or any other value on error. + */ +RNP_API rnp_result_t rnp_add_security_rule(rnp_ffi_t ffi, + const char *type, + const char *name, + uint32_t flags, + uint64_t from, + uint32_t level); + +/** + * @brief Get security rule applicable for the corresponding feature value and timestamp. + * Note: if there is no matching rule, it will fall back to the default security level + * with empty flags and `from`. + * + * @param ffi initialized FFI object. + * @param type feature type to search for. Only RNP_FEATURE_HASH_ALG is supported right now. + * @param name feature name, i.e. SHA1 or so on. + * @param time timestamp for which feature should be checked. + * @param flags if non-NULL then rule's flags will be put here. + * @param from if non-NULL then rule's from time will be put here. + * @param level cannot be NULL. Security level will be stored here. + * @return RNP_SUCCESS or any other value on error. + */ +RNP_API rnp_result_t rnp_get_security_rule(rnp_ffi_t ffi, + const char *type, + const char *name, + uint64_t time, + uint32_t * flags, + uint64_t * from, + uint32_t * level); + +/** + * @brief Remove security rule(s), matching the parameters. + * Note: use this with caution, as this may also clear default security rules, so + * all affected features would be considered of the default security level. + * + * @param ffi populated FFI structure, cannot be NULL. + * @param type type of the feature. If NULL, then all of the rules will be cleared. + * @param name name of the feature. If NULL, then all rules of the type will be cleared. + * @param level security level of the rule. + * @param flags additional flags, following are defined at the moment: + * - RNP_SECURITY_OVERRIDE : rule should match this flag + * - RNP_SECURITY_REMOVE_ALL : remove all rules for type and name. + * @param from timestamp, for when the rule should be removed. Ignored if + * RNP_SECURITY_REMOVE_ALL_FROM is specified. + * @param removed if non-NULL then number of removed rules will be stored here. + * @return RNP_SUCCESS on success or any other value on error. Please note that if no rules are + * matched, execution will be marked as successful. Use the `removed` parameter to + * check for this case. + */ +RNP_API rnp_result_t rnp_remove_security_rule(rnp_ffi_t ffi, + const char *type, + const char *name, + uint32_t level, + uint32_t flags, + uint64_t from, + size_t * removed); + +/** * @brief Request password via configured FFI's callback * * @param ffi initialized FFI structure @@ -957,6 +1067,37 @@ const char * code, const char * reason); +/** + * @brief Check whether Curve25519 secret key's bits are correctly set, i.e. 3 least + * significant bits are zero and key is exactly 255 bits in size. See RFC 7748, section + * 5 for the details. RNP interpreted RFC requirements in the way that Curve25519 secret + * key is random 32-byte string, which bits are correctly tweaked afterwards within + * secret key operation. However, for compatibility reasons, it would be more correct to + * store/transfer secret key with bits already tweaked. + * + * Note: this operation requires unlocked secret key, so make sure to call + * rnp_key_lock() afterwards. + * + * @param key key handle, cannot be NULL. Must be ECDH Curve25519 unlocked secret key. + * @param result true will be stored here if secret key's low/high bits are not correctly set. + * In this case you may need to call `rnp_key_25519_bits_tweak()` on it to set + * bits to correct values so exported secret key will be compatible with + * implementations which do not tweak these bits automatically. + * @return RNP_SUCCESS or error code if failed. + */ +RNP_API rnp_result_t rnp_key_25519_bits_tweaked(rnp_key_handle_t key, bool *result); + +/** + * @brief Make sure Curve25519 secret key's least significant and most significant bits are + * correctly set, see rnp_key_25519_bits_tweaked() documentation for the details. + * Note: this operation requires unprotected secret key since it would modify secret + * key's data, so make sure to call rnp_key_protect() afterwards. + * + * @param key key handle, cannot be NULL. Must be ECDH Curve25519 unprotected secret key. + * @return RNP_SUCCESS or error code if failed. + */ +RNP_API rnp_result_t rnp_key_25519_bits_tweak(rnp_key_handle_t key); + /** remove a key from keyring(s) * Note: you need to call rnp_save_keys() to write updated keyring(s) out. * Other handles of the same key should not be used after this call. @@ -1227,6 +1368,15 @@ */ RNP_API rnp_result_t rnp_signature_get_creation(rnp_signature_handle_t sig, uint32_t *create); +/** Get the signature expiration time as number of seconds after creation time + * + * @param sig signature handle. + * @param expires on success result will be stored here. Cannot be NULL. + * @return RNP_SUCCESS or error code if failed. + */ +RNP_API rnp_result_t rnp_signature_get_expiration(rnp_signature_handle_t sig, + uint32_t * expires); + /** Get signer's key id from the signature. * Note: if key id is not available from the signature then NULL value will * be stored to result. @@ -2733,6 +2883,21 @@ */ RNP_API rnp_result_t rnp_output_armor_set_line_length(rnp_output_t output, size_t llen); +/** + * @brief Return cryptographic backend library name. + * + * @return Backend name string. Currently supported + * backends are "Botan" and "OpenSSL". + */ +RNP_API const char *rnp_backend_string(); + +/** + * @brief Return cryptographic backend library version. + * + * @return Version string. + */ +RNP_API const char *rnp_backend_version(); + #if defined(__cplusplus) } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/include/rnp.h thunderbird-91.8.1+build1/comm/third_party/rnp/include/rnp.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/include/rnp.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/include/rnp.h 2022-04-15 07:49:22.000000000 +0000 @@ -35,7 +35,6 @@ #include "types.h" #include "pass-provider.h" #include "key-provider.h" -#include "list.h" #include "crypto/rng.h" #include #include "utils.h" diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/.lgtm.yml thunderbird-91.8.1+build1/comm/third_party/rnp/.lgtm.yml --- thunderbird-91.7.0+build2/comm/third_party/rnp/.lgtm.yml 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/.lgtm.yml 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,32 @@ +path_classifiers: + test: + # Report alerts for Python tests. + - exclude: src/tests/*.py +extraction: + cpp: + prepare: + packages: + - libjson-c-dev + after_prepare: + - pwd + - mkdir botan_build + - mkdir botan_install + - export BOTAN_INSTALL=$(pwd)/botan_install + - git clone --depth 1 --branch 2.17.3 https://github.com/randombit/botan botan_build + - pushd botan_build + - export BOTAN_MODULES=$(<${LGTM_SRC}/ci/botan-modules tr '\n' ',') + - ./configure.py --prefix=${BOTAN_INSTALL} --with-debug-info --cxxflags="-fno-omit-frame-pointer" --without-documentation --without-openssl --build-targets=shared --minimized-build --enable-modules="$BOTAN_MODULES" + - make -j2 install + - popd + - "mkdir cmake314" + - "wget --quiet -O - https://cmake.org/files/v3.14/cmake-3.14.7-Linux-x86_64.tar.gz | tar --strip-components=1 -xz -C cmake314" + - "export PATH=$(pwd)/cmake314/bin:${PATH}" + index: + build_command: + - pwd + - mkdir rnp-build; pushd rnp-build + - cmake $LGTM_SRC -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH="${BOTAN_INSTALL}" -DDOWNLOAD_GTEST=Off -DDOWNLOAD_RUBYRNP=Off + - make -j2 + python: + python_setup: + version: "3" diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/moz.build thunderbird-91.8.1+build1/comm/third_party/rnp/moz.build --- thunderbird-91.7.0+build2/comm/third_party/rnp/moz.build 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/moz.build 2022-04-15 07:49:22.000000000 +0000 @@ -97,34 +97,44 @@ SOURCES += [ "src/common/file-utils.cpp", - "src/common/list.cpp", "src/common/str-utils.cpp", "src/common/time-utils.cpp", "src/lib/crypto.cpp", + "src/lib/crypto/backend_version.cpp", "src/lib/crypto/bn.cpp", + "src/lib/crypto/cipher.cpp", + "src/lib/crypto/cipher_botan.cpp", "src/lib/crypto/dsa.cpp", "src/lib/crypto/ec.cpp", + "src/lib/crypto/ec_curves.cpp", "src/lib/crypto/ecdh.cpp", + "src/lib/crypto/ecdh_utils.cpp", "src/lib/crypto/ecdsa.cpp", "src/lib/crypto/eddsa.cpp", "src/lib/crypto/elgamal.cpp", "src/lib/crypto/hash.cpp", + "src/lib/crypto/hash_common.cpp", "src/lib/crypto/mem.cpp", "src/lib/crypto/mpi.cpp", "src/lib/crypto/rng.cpp", "src/lib/crypto/rsa.cpp", "src/lib/crypto/s2k.cpp", + "src/lib/crypto/sha1cd/hash_sha1cd.cpp", + "src/lib/crypto/sha1cd/sha1.c", + "src/lib/crypto/sha1cd/ubc_check.c", "src/lib/crypto/signatures.cpp", "src/lib/crypto/sm2.cpp", "src/lib/crypto/symmetric.cpp", "src/lib/fingerprint.cpp", "src/lib/generate-key.cpp", + "src/lib/json-utils.cpp", "src/lib/key-provider.cpp", "src/lib/logging.cpp", - "src/lib/misc.cpp", "src/lib/pass-provider.cpp", "src/lib/pgp-key.cpp", "src/lib/rnp.cpp", + "src/lib/sec_profile.cpp", + "src/lib/utils.cpp", # librekey "src/librekey/key_store_g10.cpp", "src/librekey/key_store_kbx.cpp", diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/README.adoc thunderbird-91.8.1+build1/comm/third_party/rnp/README.adoc --- thunderbird-91.7.0+build2/comm/third_party/rnp/README.adoc 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/README.adoc 2022-04-15 07:49:22.000000000 +0000 @@ -4,6 +4,7 @@ image:https://github.com/rnpgp/rnp/workflows/ubuntu/badge.svg["Ubuntu Build Status", link="https://github.com/rnpgp/rnp/actions?workflow=ubuntu"] image:https://github.com/rnpgp/rnp/workflows/centos7/badge.svg["CentOS 7 Build Status", link="https://github.com/rnpgp/rnp/actions?workflow=centos7"] image:https://github.com/rnpgp/rnp/workflows/windows/badge.svg["Windows Build Status", link="https://github.com/rnpgp/rnp/actions?workflow=windows"] +image:https://github.com/rnpgp/rnp/workflows/nix/badge.svg["Nix Build Status", link="https://github.com/rnpgp/rnp/actions?workflow=nix"] image:https://img.shields.io/cirrus/github/rnpgp/rnp?label=freebsd&logo=cirrus%20ci["FreeBSD Build Status", link="https://cirrus-ci.com/github/rnpgp/rnp"] image:https://img.shields.io/coverity/scan/12616.svg["Coverity Scan Build Status", link="https://scan.coverity.com/projects/rnpgp-rnp"] @@ -25,6 +26,7 @@ * Fedora 25 * RHEL/CentOS 7 * Ubuntu 14.04 LTS, 16.04 LTS, 18.04 +* NixOS / Nix Upcoming supported platforms: @@ -38,6 +40,8 @@ == link:docs/c-usage.adoc[Using the RNP C API in your projects] +== link:docs/signing-keys.adoc[PGP keys used for signing source code] + == Versioning RNP follows the http://semver.org/[semantic versioning] syntax. diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/rnp.symbols thunderbird-91.8.1+build1/comm/third_party/rnp/rnp.symbols --- thunderbird-91.7.0+build2/comm/third_party/rnp/rnp.symbols 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/rnp.symbols 2022-04-15 07:49:22.000000000 +0000 @@ -1,3 +1,6 @@ +rnp_add_security_rule +rnp_backend_string +rnp_backend_version rnp_buffer_clear rnp_buffer_destroy rnp_calculate_iterations @@ -5,10 +8,8 @@ rnp_decrypt rnp_detect_homedir_info rnp_detect_key_format -rnp_disable_debug rnp_dump_packets_to_json rnp_dump_packets_to_output -rnp_enable_debug rnp_enarmor rnp_ffi_create rnp_ffi_destroy @@ -27,6 +28,7 @@ rnp_get_public_key_data rnp_get_secret_key_count rnp_get_secret_key_data +rnp_get_security_rule rnp_guess_contents rnp_identifier_iterator_create rnp_identifier_iterator_destroy @@ -37,6 +39,8 @@ rnp_input_from_callback rnp_input_from_memory rnp_input_from_path +rnp_key_25519_bits_tweak +rnp_key_25519_bits_tweaked rnp_key_add_uid rnp_key_allows_usage rnp_key_export @@ -46,6 +50,7 @@ rnp_key_get_bits rnp_key_get_creation rnp_key_get_curve +rnp_key_get_default_key rnp_key_get_dsa_qbits rnp_key_get_expiration rnp_key_get_fprint @@ -185,11 +190,13 @@ rnp_output_write rnp_recipient_get_alg rnp_recipient_get_keyid +rnp_remove_security_rule rnp_request_password rnp_result_to_string rnp_save_keys rnp_signature_get_alg rnp_signature_get_creation +rnp_signature_get_expiration rnp_signature_get_hash_alg rnp_signature_get_keyid rnp_signature_get_signer diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/CMakeLists.txt thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/CMakeLists.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/CMakeLists.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/CMakeLists.txt 2022-04-15 07:49:22.000000000 +0000 @@ -23,7 +23,6 @@ # POSSIBILITY OF SUCH DAMAGE. add_library(rnp-common OBJECT - list.cpp str-utils.cpp file-utils.cpp time-utils.cpp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/list.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/list.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/list.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/list.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include -#include -#include "list.h" - -struct list_head { - list_item *first, *last; - size_t length; -}; - -struct list_item { - list_head *head; - list_item *prev, *next; -}; - -static list_item * -get_item_ptr(list_item *item) -{ - return item ? (item - 1) : NULL; -} - -static list_item * -get_data_ptr(list_item *item) -{ - return item ? (item + 1) : NULL; -} - -size_t -list_length(list head) -{ - return head ? head->length : 0; -} - -static list_item * -list_do_insert(list *lst, list_item *where, const void *data, size_t data_size) -{ - if (!lst || !data_size) { - return NULL; - } - bool allocated_head = false; - if (!*lst) { - *lst = (list_head *) calloc(1, sizeof(**lst)); - allocated_head = true; - if (!*lst) { - return NULL; - } - } - list head = *lst; - - list_item *item = (list_item *) malloc(sizeof(*item) + data_size); - if (!item) { - if (allocated_head) { - free(*lst); - *lst = NULL; - } - return NULL; - } - if (data) { - memset(item, 0, sizeof(*item)); - memcpy(get_data_ptr(item), data, data_size); - } else { - memset(item, 0, sizeof(*item) + data_size); - } - item->head = head; - - if (!head->first) { - // new list - head->first = head->last = item; - } else if (where) { - // insert before - item->next = where; - item->prev = where->prev; - if (where->prev) { - where->prev->next = item; - } - where->prev = item; - if (head->first == where) { - head->first = item; - } - } else { - // append to end - item->prev = head->last; - head->last->next = item; - head->last = item; - } - head->length++; - return item; -} - -list_item * -list_append(list *lst, const void *data, size_t data_size) -{ - list_item *item = list_do_insert(lst, NULL, data, data_size); - return get_data_ptr(item); -} - -list_item * -list_insert_after(list_item *where, const void *data, size_t data_size) -{ - where = get_item_ptr(where); - if (!where) { - return NULL; - } - list_item *item = list_do_insert(&where->head, where->next, data, data_size); - return get_data_ptr(item); -} - -list_item * -list_insert_before(list_item *where, const void *data, size_t data_size) -{ - where = get_item_ptr(where); - if (!where) { - return NULL; - } - list_item *item = list_do_insert(&where->head, where, data, data_size); - return get_data_ptr(item); -} - -list_item * -list_insert(list *lst, const void *data, size_t data_size) -{ - if (!lst) { - return NULL; - } - list head = *lst; - list_item *where = head ? head->first : NULL; - list_item *item = list_do_insert(lst, where, data, data_size); - return get_data_ptr(item); -} - -bool -list_is_member(list head, list_item *item) -{ - if (!head || !item) { - return false; - } - return get_item_ptr(item)->head == head; -} - -list_item * -list_front(list head) -{ - return head ? get_data_ptr(head->first) : NULL; -} - -list_item * -list_back(list head) -{ - return head ? get_data_ptr(head->last) : NULL; -} - -static list_item * -list_do_find(list_item *item, const void *data, size_t data_size) -{ - if (!item || !data || !data_size) { - return NULL; - } - for (; item; item = item->next) { - if (memcmp(get_data_ptr(item), data, data_size) == 0) { - break; - } - } - return item; -} - -list_item * -list_find(list head, const void *data, size_t data_size) -{ - list_item *item = list_do_find(get_item_ptr(list_front(head)), data, data_size); - return get_data_ptr(item); -} - -list_item * -list_find_next(list_item *from, const void *data, size_t data_size) -{ - from = get_item_ptr(list_next(from)); - list_item *item = list_do_find(from, data, data_size); - return get_data_ptr(item); -} - -list_item * -list_next(list_item *item) -{ - if (!item || !(item = get_item_ptr(item)->next)) { - return NULL; - } - return get_data_ptr(item); -} - -list_item * -list_prev(list_item *item) -{ - if (!item || !(item = get_item_ptr(item)->prev)) { - return NULL; - } - return get_data_ptr(item); -} - -list_item * -list_at(list lst, size_t index) -{ - list_item *res = NULL; - if (index >= list_length(lst)) { - return NULL; - } - - res = list_front(lst); - while (res && index) { - index--; - res = list_next(res); - } - - return res; -} - -void -list_remove(list_item *item) -{ - if (!item) { - return; - } - item = get_item_ptr(item); - list head = item->head; - - if (item->next) { - item->next->prev = item->prev; - } - if (item->prev) { - item->prev->next = item->next; - } - if (item == head->first) { - head->first = item->next; - } - if (item == head->last) { - head->last = item->prev; - } - free(item); - head->length--; -} - -void -list_destroy(list *lst) -{ - if (!lst || !*lst) { - return; - } - list head = *lst; - list_item *item = head->first; - while (item) { - list_item *next = item->next; - free(item); - item = next; - } - free(head); - *lst = NULL; -} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/list.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/list.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/list.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/list.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** Doubly linked list - * @file - */ -#ifndef RNP_LIST_H -#define RNP_LIST_H - -#include -#include - -/** - * @private - * Note that all list_item pointers returned from the - * API are actually pointers directly to your data, - * and thus can be directly cast to the appropriate - * type. - * - * The code below will print: - * first - * second - * - * @code - * // always initialize to NULL - * list lst = NULL; - * list_append(&lst, "second", strlen("second") + 1); - * list_insert(&lst, "first", strlen("first") + 1); - * assert(list_length(lst) == 2); - * - * list_item *item = list_front(lst); - * while (item) { - * printf("%s\n", (char*)item); - * item = list_next(item); - * } - * @endcode - * - * Searching: - * The code below searches for the value 1 and will - * output: - * Found 1 - * Found 1 - * Found 1 - * - * @code - * list lst = NULL; - * static const int some_ints[] = {0, 1, 1, 2, 3, 4, 1}; - * for (int i = 0; i < sizeof(some_ints) / sizeof(some_ints[0]); i++) { - * list_append(&lst, &some_ints[i], sizeof(some_ints[i])); - * } - * - * int one = 1; - * list_item *item = list_find(lst, &one, sizeof(one)); - * while (item) { - * printf("Found %d\n", *(int*)item); - * item = list_find_next(item, &one, sizeof(one)); - * } - * @endcode - */ - -typedef struct list_head *list; -typedef struct list_head list_head; -typedef struct list_item list_item; - -/** @private - * append data to the list - * - * @param lst pointer to the list, which should not be NULL - * @param data pointer to the data. If NULL, the new item will - * be zero-initialized. Otherwise, the data will be - * copied to the new item - * @param data_size size of the data, which must be >= 1 - * @return the new item or NULL if memory allocation failed - **/ -list_item *list_append(list *lst, const void *data, size_t data_size); - -/** @private - * insert data at the front the list - * - * @param lst pointer to the list, which should not be NULL - * @param data pointer to the data. If NULL, the new item will - * be zero-initialized. Otherwise, the data will be - * copied to the new item. - * @param data_size size of the data, which must be >= 1 - * @return the new item or NULL if memory allocation failed - **/ -list_item *list_insert(list *lst, const void *data, size_t data_size); - -/** @private - * insert data before a particular item in the list - * - * @param where pointer to the item, which should not be NULL - * @param data pointer to the data. If NULL, the new item will - * be zero-initialized. Otherwise, the data will be - * copied to the new item. - * @param data_size size of the data, which must be >= 1 - * @return the new item or NULL if memory allocation failed - **/ -list_item *list_insert_before(list_item *where, const void *data, size_t data_size); - -/** @private - * insert data after a particular item in the list - * - * @param where pointer to the item, which should not be NULL - * @param data pointer to the data. If NULL, the new item will - * be zero-initialized. Otherwise, the data will be - * copied to the new item. - * @param data_size size of the data, which must be >= 1 - * @return the new item or NULL if memory allocation failed - **/ -list_item *list_insert_after(list_item *where, const void *data, size_t data_size); - -/** @private - * check if an item is a member of a list - * - * This is a quick operation, it does not need to traverse the list. - * - * @param lst the list - * @param item pointer to the item, which should not be NULL - * @return true if the item is a member of the list, false otherwise - **/ -bool list_is_member(list lst, list_item *item); - -/** @private - * get the number of items in a list - * - * @param lst the list - * @return the number of items in the list - **/ -size_t list_length(list lst); - -/** @private - * remove an item from a list - * - * @param item pointer to the item to remove, which should not be NULL - **/ -void list_remove(list_item *item); - -/** @private - * destroy a list and all items - * - * @param lst pointer to the list, which should not be NULL - **/ -void list_destroy(list *lst); - -/** @private - * get the first item in a list - * - * @param lst the list - * @return pointer to the item, if any, otherwise NULL - **/ -list_item *list_front(list lst); - -/** @private - * get the last item in a list - * - * @param lst the list - * @return pointer to the item, if any, otherwise - **/ -list_item *list_back(list lst); - -/** @private - * search the list for some data - * - * **Note**: that this will do a byte-for-byte comparison - * of size data_size, so it may not be very efficient, - * depending on the data type stored. - * - * @param lst the list - * @param data pointer to the data, which should not be NULL - * @param data_size size of the data, which must be >= 1 - * @return pointer to the found item, if any, otherwise NULL - **/ -list_item *list_find(list lst, const void *data, size_t data_size); - -/** @private - * search the list for some data, starting after the specified - * location - * - * **Note**: that this will do a byte-for-byte comparison - * of size data_size, so it may not be very efficient, - * depending on the data type stored. - * - * @param from pointer to the item, after which the search - * will begin. Should not be NULL. - * @param data pointer to the data, which should not be NULL - * @param data_size size of the data, which must be >= 1 - * @return pointer to the found item, if any, otherwise NULL - **/ -list_item *list_find_next(list_item *from, const void *data, size_t data_size); - -/** @private - * get the next item in a list, if any - * - * @param item pointer to the list item, which should not be NULL - * @return pointer to the next item, if any, otherwise NULL - **/ -list_item *list_next(list_item *item); - -/** @private - * get the previous item in a list, if any - * - * @param item pointer to the list item, which should not be NULL - * @return pointer to the previous item, if any, otherwise NULL - **/ -list_item *list_prev(list_item *item); - -/** @private - * get the list item at specified index - * - * @param lst the list - * @param index index of the element, 0 is list head - * @return pointer to the item at specified index, if any, otherwise NULL - **/ -list_item *list_at(list lst, size_t index); - -#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/str-utils.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/str-utils.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/str-utils.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/str-utils.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -29,6 +29,7 @@ #include #include +#include #include "str-utils.h" #ifdef _WIN32 #include @@ -38,8 +39,9 @@ using std::size_t; using std::strlen; +namespace rnp { char * -rnp_strip_eol(char *s) +strip_eol(char *s) { size_t len = strlen(s); @@ -51,7 +53,21 @@ } bool -rnp_is_blank_line(const char *line, size_t len) +strip_eol(std::string &s) +{ + size_t len = s.size(); + while (len && ((s[len - 1] == '\n') || (s[len - 1] == '\r'))) { + len--; + } + if (len == s.size()) { + return false; + } + s.resize(len); + return true; +} + +bool +is_blank_line(const char *line, size_t len) { for (size_t i = 0; i < len && line[i]; i++) { if (line[i] != ' ' && line[i] != '\t' && line[i] != '\r') { @@ -61,6 +77,20 @@ return true; } +bool +str_case_eq(const char *s1, const char *s2) +{ + while (*s1 && *s2) { + if (std::tolower(*s1) != std::tolower(*s2)) { + return false; + } + s1++; + s2++; + } + return !*s1 && !*s2; +} +} // namespace rnp + #ifdef _WIN32 std::wstring wstr_from_utf8(const char *s) diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/str-utils.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/str-utils.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/common/str-utils.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/common/str-utils.h 2022-04-15 07:49:22.000000000 +0000 @@ -27,8 +27,20 @@ #ifndef RNP_STR_UTILS_H_ #define RNP_STR_UTILS_H_ -char *rnp_strip_eol(char *s); -bool rnp_is_blank_line(const char *line, size_t len); +#include + +namespace rnp { +char *strip_eol(char *s); +/** + * @brief Strip EOL characters from the string's end. + * + * @param s string to check + * @return true if EOL was found and stripped, or false otherwise. + */ +bool strip_eol(std::string &s); +bool is_blank_line(const char *line, size_t len); +bool str_case_eq(const char *s1, const char *s2); +} // namespace rnp #ifdef _WIN32 #include std::wstring wstr_from_utf8(const char *s); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/examples/verify.c thunderbird-91.8.1+build1/comm/third_party/rnp/src/examples/verify.c --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/examples/verify.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/examples/verify.c 2022-04-15 07:49:21.000000000 +0000 @@ -40,7 +40,16 @@ rnp_input_t input = NULL; char filename[32] = {0}; if (strcmp(identifier_type, "keyid")) { - return; + if (strcmp(identifier_type, "fingerprint")) { + fprintf(stdout, "Unsupported key search: %s = %s\n", identifier_type, identifier); + return; + } + /* if we search by fp then keyid is last 16 chars */ + if (strlen(identifier) < 40) { + fprintf(stdout, "Invalid fingerprint: %s\n", identifier); + return; + } + identifier += 24; } snprintf(filename, sizeof(filename), "key-%s-%s.asc", identifier, secret ? "sec" : "pub"); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/fuzzing/keyring_g10.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/fuzzing/keyring_g10.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/fuzzing/keyring_g10.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/fuzzing/keyring_g10.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -28,6 +28,7 @@ #include "../lib/pgp-key.h" #include "../librekey/key_store_g10.h" #include "../librepgp/stream-common.h" +#include "../lib/sec_profile.hpp" #ifdef RNP_RUN_TESTS int keyring_g10_LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); @@ -38,8 +39,9 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) #endif { - rnp_key_store_t ks; - pgp_source_t memsrc = {}; + rnp::SecurityContext ctx; + rnp_key_store_t ks(ctx); + pgp_source_t memsrc = {}; init_mem_src(&memsrc, data, size, false); rnp_key_store_g10_from_src(&ks, &memsrc, NULL); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/fuzzing/verify.c thunderbird-91.8.1+build1/comm/third_party/rnp/src/fuzzing/verify.c --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/fuzzing/verify.c 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/fuzzing/verify.c 2022-04-15 07:49:22.000000000 +0000 @@ -27,8 +27,14 @@ #include #include "stdio.h" +#ifdef RNP_RUN_TESTS +int verify_LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); +int +verify_LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +#else int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +#endif { rnp_ffi_t ffi = NULL; rnp_input_t input = NULL; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/CMakeLists.txt thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/CMakeLists.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/CMakeLists.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/CMakeLists.txt 2022-04-15 07:49:22.000000000 +0000 @@ -31,7 +31,14 @@ # required packages find_package(JSON-C 0.11 REQUIRED) -find_package(Botan2 2.14.0 REQUIRED) +if (CRYPTO_BACKEND_BOTAN) + find_package(Botan2 2.14.0 REQUIRED) +endif() +if (CRYPTO_BACKEND_OPENSSL) + include(FindOpenSSL) + find_package(OpenSSL 1.1.1 REQUIRED) + include(FindOpenSSLFeatures) +endif() # generate a config.h include(CheckIncludeFileCXX) @@ -61,35 +68,141 @@ # generate a version.h configure_file(version.h.in version.h) -# check botan's enabled features -set(CMAKE_REQUIRED_INCLUDES "${BOTAN2_INCLUDE_DIRS}") -set(_botan_required_features - # base - BIGINT FFI HEX_CODEC PGP_S2K - # AEAD - BLOCK_CIPHER AEAD_EAX AEAD_OCB +if(CRYPTO_BACKEND_BOTAN) + # check botan's enabled features + set(CMAKE_REQUIRED_INCLUDES "${BOTAN2_INCLUDE_DIRS}") + set(_botan_required_features + # base + BIGINT FFI HEX_CODEC PGP_S2K + # symmetric ciphers + BLOCK_CIPHER AES BLOWFISH CAMELLIA CAST_128 DES IDEA + # cipher modes + MODE_CBC MODE_CFB + # RNG + AUTO_RNG AUTO_SEEDING_RNG HMAC HMAC_DRBG + # hash + CRC24 HASH MD5 SHA1 SHA2_32 SHA2_64 SHA3 RIPEMD_160 + # public-key core + DL_GROUP DL_PUBLIC_KEY_FAMILY ECC_GROUP ECC_PUBLIC_KEY_CRYPTO PUBLIC_KEY_CRYPTO + # public-key algs + CURVE_25519 DSA ECDH ECDSA ED25519 ELGAMAL RSA + # public-key operations etc + EME_PKCS1v15 EMSA_PKCS1 EMSA_RAW KDF_BASE RFC3394_KEYWRAP SP800_56A + ) + # SM2 algorithms suite + if (ENABLE_SM2) + list(APPEND _botan_required_features SM2 SM3 SM4) + endif() + # AEAD algorithms + if (ENABLE_AEAD) + list(APPEND _botan_required_features AEAD_EAX AEAD_OCB) + endif() + # Twofish + if (ENABLE_TWOFISH) + list(APPEND _botan_required_features TWOFISH) + endif() + foreach(feature ${_botan_required_features}) + check_cxx_symbol_exists("BOTAN_HAS_${feature}" botan/build.h _botan_has_${feature}) + if (NOT _botan_has_${feature}) + message(FATAL_ERROR "A required botan feature is missing: ${feature}") + endif() + endforeach() + set(CMAKE_REQUIRED_INCLUDES) +endif() +if(CRYPTO_BACKEND_OPENSSL) + # check OpenSSL features + set(_openssl_required_features # symmetric ciphers - AES BLOWFISH CAMELLIA CAST_128 DES IDEA RIPEMD_160 SM4 TWOFISH - # cipher modes - MODE_CBC MODE_CFB - # RNG - AUTO_RNG AUTO_SEEDING_RNG HMAC HMAC_DRBG - # hash - CRC24 HASH MD5 SHA1 SHA2_32 SHA2_64 SHA3 SM3 - # public-key core - DL_GROUP DL_PUBLIC_KEY_FAMILY ECC_GROUP ECC_PUBLIC_KEY_CRYPTO PUBLIC_KEY_CRYPTO - # public-key algs - CURVE_25519 DSA ECDH ECDSA ED25519 ELGAMAL RSA SM2 - # public-key operations etc - EME_PKCS1v15 EMSA_PKCS1 EMSA_RAW KDF_BASE RFC3394_KEYWRAP SP800_56A -) -foreach(feature ${_botan_required_features}) - check_cxx_symbol_exists("BOTAN_HAS_${feature}" botan/build.h _botan_has_${feature}) - if (NOT _botan_has_${feature}) - message(FATAL_ERROR "A required botan feature is missing: ${feature}") + AES-128-ECB AES-192-ECB AES-256-ECB AES-128-CBC AES-192-CBC AES-256-CBC + BF-ECB CAMELLIA-128-ECB CAMELLIA-192-ECB CAMELLIA-256-ECB CAST5-ECB + DES-EDE3 IDEA-ECB IDEA-CBC + # hashes + MD5 SHA1 SHA224 SHA256 SHA384 SHA512 SHA3-256 SHA3-512 RIPEMD160 + # curves + PRIME256V1 SECP384R1 SECP521R1 SECP256K1 + # public key + RSAENCRYPTION DSAENCRYPTION DHKEYAGREEMENT ID-ECPUBLICKEY X25519 ED25519 + ) + # SM2 algorithms suite + if (ENABLE_SM2) + list(APPEND _openssl_required_features SM2 SM3 SM4-ECB) endif() -endforeach() -set(CMAKE_REQUIRED_INCLUDES) + # Brainpool curves + if (ENABLE_BRAINPOOL) + list(APPEND _openssl_required_features BRAINPOOLP256R1 BRAINPOOLP384R1 BRAINPOOLP512R1) + endif() + foreach(feature ${_openssl_required_features}) + message(STATUS "Looking for OpenSSL feature ${feature}") + OpenSSLHasFeature("${feature}" _openssl_has_${feature}) + if (NOT _openssl_has_${feature}) + message(FATAL_ERROR "A required OpenSSL feature is missing: ${feature}") + endif() + message(STATUS "Looking for OpenSSL feature ${feature} - found") + endforeach() +endif() + +if(CRYPTO_BACKEND_OPENSSL) + set(CRYPTO_SOURCES + crypto/bn_ossl.cpp + crypto/dsa_ossl.cpp + crypto/ec_curves.cpp + crypto/ec_ossl.cpp + crypto/ecdh_utils.cpp + crypto/ecdh_ossl.cpp + crypto/ecdsa_ossl.cpp + crypto/eddsa_ossl.cpp + crypto/dl_ossl.cpp + crypto/elgamal_ossl.cpp + crypto/hash_common.cpp + crypto/hash_ossl.cpp + crypto/hash_crc24.cpp + crypto/mpi.cpp + crypto/rng_ossl.cpp + crypto/rsa_ossl.cpp + crypto/s2k.cpp + crypto/s2k_ossl.cpp + crypto/symmetric_ossl.cpp + crypto/signatures.cpp + crypto/mem_ossl.cpp + crypto/cipher.cpp + crypto/cipher_ossl.cpp + ) + if(ENABLE_SM2) + list(APPEND CRYPTO_SOURCES crypto/sm2_ossl.cpp) + endif() +elseif(CRYPTO_BACKEND_BOTAN) + set(CRYPTO_SOURCES + crypto/bn.cpp + crypto/dsa.cpp + crypto/ec_curves.cpp + crypto/ec.cpp + crypto/ecdh_utils.cpp + crypto/ecdh.cpp + crypto/ecdsa.cpp + crypto/eddsa.cpp + crypto/elgamal.cpp + crypto/hash_common.cpp + crypto/hash.cpp + crypto/mpi.cpp + crypto/rng.cpp + crypto/rsa.cpp + crypto/s2k.cpp + crypto/symmetric.cpp + crypto/signatures.cpp + crypto/mem.cpp + crypto/cipher.cpp + crypto/cipher_botan.cpp + ) + if(ENABLE_SM2) + list(APPEND CRYPTO_SOURCES crypto/sm2.cpp) + endif() +else() + message(FATAL_ERROR "Unknown crypto backend: ${CRYPTO_BACKEND}.") +endif() +list(APPEND CRYPTO_SOURCES crypto/backend_version.cpp) + +# sha11collisiondetection sources +list(APPEND CRYPTO_SOURCES crypto/sha1cd/hash_sha1cd.cpp crypto/sha1cd/sha1.c crypto/sha1cd/ubc_check.c) add_library(librnp-obj OBJECT # librepgp @@ -109,34 +222,34 @@ ../librekey/key_store_pgp.cpp ../librekey/rnp_key_store.cpp - crypto/bn.cpp - crypto/dsa.cpp - crypto/ec.cpp - crypto/ecdh.cpp - crypto/ecdsa.cpp - crypto/eddsa.cpp - crypto/elgamal.cpp - crypto/hash.cpp - crypto/mpi.cpp - crypto/rng.cpp - crypto/rsa.cpp - crypto/s2k.cpp - crypto/sm2.cpp - crypto/symmetric.cpp - crypto/signatures.cpp - crypto/mem.cpp + # cryptography + ${CRYPTO_SOURCES} + + # other sources + sec_profile.cpp crypto.cpp fingerprint.cpp generate-key.cpp key-provider.cpp logging.cpp - misc.cpp + json-utils.cpp + utils.cpp pass-provider.cpp pgp-key.cpp rnp.cpp $ ) +get_target_property(_comp_options librnp-obj COMPILE_OPTIONS) +string(REGEX MATCH "\\-fsanitize=[a-z,]*undefined" _comp_sanitizers "${_comp_options}" "${CMAKE_C_FLAGS}") +if (ENABLE_SANITIZERS OR _comp_sanitizers) + # sha1cd attempts to use unaligned access for optimisations on intel CPUs + # CFLAGS is checked as sanitizers may be enabled without CMake var + set_source_files_properties(crypto/sha1cd/sha1.c + PROPERTIES COMPILE_DEFINITIONS "SHA1DC_FORCE_ALIGNED_ACCESS" + ) +endif() + set_target_properties(librnp-obj PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories(librnp-obj PUBLIC @@ -148,11 +261,13 @@ "${CMAKE_CURRENT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/src" ) -target_link_libraries(librnp-obj - PRIVATE - Botan2::Botan2 - JSON-C::JSON-C -) +target_link_libraries(librnp-obj PRIVATE JSON-C::JSON-C) +if (CRYPTO_BACKEND_BOTAN) + target_link_libraries(librnp-obj PRIVATE Botan2::Botan2) +elseif (CRYPTO_BACKEND_OPENSSL) + target_link_libraries(librnp-obj PRIVATE OpenSSL::Crypto) +endif() + set_target_properties(librnp-obj PROPERTIES CXX_VISIBILITY_PRESET hidden) if (TARGET BZip2::BZip2) target_link_libraries(librnp-obj PRIVATE BZip2::BZip2) @@ -177,6 +292,15 @@ if (BUILD_SHARED_LIBS) add_library(librnp-static STATIC $ $) + # Limit symbols export only to rnp_* functions. + if (APPLE) + # use -export_symbols_list on Apple OSs + target_link_options(librnp PRIVATE -Wl,-exported_symbols_list "${CMAKE_CURRENT_SOURCE_DIR}/librnp.symbols") + set_target_properties(librnp PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/librnp.symbols") + elseif(NOT WIN32) + target_link_options(librnp PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/librnp.vsc") + set_target_properties(librnp PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/librnp.vsc") + endif() else() add_library(librnp-static ALIAS librnp) endif() @@ -190,9 +314,11 @@ endforeach() generate_export_header(librnp - BASE_NAME rnp/rnp + BASE_NAME rnp EXPORT_MACRO_NAME RNP_API + EXPORT_FILE_NAME rnp/rnp_export.h STATIC_DEFINE RNP_STATIC + INCLUDE_GUARD_NAME RNP_EXPORT ) # This has precedence and can cause some confusion when the binary diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/config.h.in thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/config.h.in --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/config.h.in 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/config.h.in 2022-04-15 07:49:21.000000000 +0000 @@ -24,7 +24,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#define PACKAGE_STRING "rnp 0.15.2+git20210806.dd923a4e.MZLA" +#define PACKAGE_STRING "rnp 0.16+git20220124.f06439f7.MZLA" #define PACKAGE_BUGREPORT "https://bugzilla.mozilla.org/enter_bug.cgi?product=Thunderbird" #undef HAVE_BZLIB_H @@ -50,10 +50,18 @@ #undef HAVE__O_BINARY #undef HAVE__TEMPNAM +#undef CRYPTO_BACKEND_BOTAN +#undef CRYPTO_BACKEND_OPENSSL + +#undef ENABLE_SM2 +#undef ENABLE_AEAD +#undef ENABLE_TWOFISH +#undef ENABLE_BRAINPOOL + /* Macro _GLIBCXX_USE_CXX11_ABI was first introduced with GCC 5.0, which * we assume to be bundled with a sane implementation of std::regex. */ -#if !defined(__GNUC__) || defined(_GLIBCXX_USE_CXX11_ABI) || defined(MSVC) +#if !defined(__GNUC__) || defined(_GLIBCXX_USE_CXX11_ABI) || defined(MSVC) || \ + (defined(__clang__) && (__clang_major__ >= 4)) #define RNP_USE_STD_REGEX 1 #endif - diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/backend_version.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/backend_version.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/backend_version.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/backend_version.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "backend_version.h" +#include "logging.h" +#if defined(CRYPTO_BACKEND_BOTAN) +#include +#elif defined(CRYPTO_BACKEND_OPENSSL) +#include +#include +#include +#include "config.h" +#ifndef RNP_USE_STD_REGEX +#include +#else +#include +#endif +#endif +#include + +namespace rnp { + +const char * +backend_string() +{ +#if defined(CRYPTO_BACKEND_BOTAN) + return "Botan"; +#elif defined(CRYPTO_BACKEND_OPENSSL) + return "OpenSSL"; +#else +#error "Unknown backend" +#endif +} + +const char * +backend_version() +{ +#if defined(CRYPTO_BACKEND_BOTAN) + return Botan::short_version_cstr(); +#elif defined(CRYPTO_BACKEND_OPENSSL) + /* Use regexp to retrieve version (second word) from version string + * like "OpenSSL 1.1.1l 24 Aug 2021" + * */ + static char version[32] = {}; + if (version[0]) { + return version; + } + const char *reg = "OpenSSL (([0-9]\\.[0-9]\\.[0-9])[a-z]*(-beta[0-9])*(-dev)*) "; +#ifndef RNP_USE_STD_REGEX + static regex_t r; + regmatch_t matches[5]; + const char * ver = OpenSSL_version(OPENSSL_VERSION); + + if (!strlen(version)) { + if (regcomp(&r, reg, REG_EXTENDED) != 0) { + RNP_LOG("failed to compile regexp"); + return "unknown"; + } + } + if (regexec(&r, ver, 5, matches, 0) != 0) { + return "unknown"; + } + assert(sizeof(version) > matches[1].rm_eo - matches[1].rm_so); + memcpy(version, ver + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); + version[matches[1].rm_eo - matches[1].rm_so] = '\0'; +#else + static std::regex re(reg, std::regex_constants::extended); + std::smatch result; + std::string ver = OpenSSL_version(OPENSSL_VERSION); + if (!std::regex_search(ver, result, re)) { + return "unknown"; + } + assert(sizeof(version) > result[1].str().size()); + strncpy(version, result[1].str().c_str(), sizeof(version) - 1); +#endif + return version; +#else +#error "Unknown backend" +#endif +} + +} // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/backend_version.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/backend_version.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/backend_version.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/backend_version.h 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CRYPTO_BACKEND_VERSION_H_ +#define CRYPTO_BACKEND_VERSION_H_ + +#include "config.h" + +namespace rnp { + +const char *backend_string(); + +const char *backend_version(); + +} // namespace rnp + +#endif // CRYPTO_BACKEND_VERSION_H_ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/bn.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/bn.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/bn.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/bn.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -35,31 +35,45 @@ /* the bignum_t API tends to have more const poisoning */ /* these wrappers also check the arguments passed for sanity */ +/* store in unsigned [big endian] format */ +int +bn_bn2bin(const bignum_t *a, unsigned char *b) +{ + if (!a || !b) { + return -1; + } + return botan_mp_to_bin(a->mp, b); +} + bignum_t * -bn_bin2bn(const uint8_t *data, int len, bignum_t *ret) +mpi2bn(const pgp_mpi_t *val) { - assert(data); - if (!data) { - RNP_LOG("NULL data."); + assert(val); + if (!val) { + RNP_LOG("NULL val."); return NULL; } - if (!ret) { - ret = bn_new(); - } - if (!ret) { + bignum_t *res = bn_new(); + if (!res) { return NULL; } - return !botan_mp_from_bin(ret->mp, data, len) ? ret : NULL; + if (botan_mp_from_bin(res->mp, val->mpi, val->len)) { + bn_free(res); + res = NULL; + } + return res; } -/* store in unsigned [big endian] format */ -int -bn_bn2bin(const bignum_t *a, unsigned char *b) +bool +bn2mpi(const bignum_t *bn, pgp_mpi_t *val) { - if (!a || !b) { - return -1; + val->len = bn_num_bytes(*bn); + if (val->len > PGP_MPINT_SIZE) { + RNP_LOG("Too large MPI."); + val->len = 0; + return false; } - return botan_mp_to_bin(a->mp, b); + return bn_bn2bin(bn, val->mpi) == 0; } bignum_t * @@ -82,18 +96,12 @@ } } -bool -bn_num_bits(const bignum_t *a, size_t *bits) -{ - return a && !botan_mp_num_bits(a->mp, bits); -} - -bool -bn_num_bytes(const bignum_t *a, size_t *bits) +size_t +bn_num_bytes(const bignum_t &a) { - if (bn_num_bits(a, bits)) { - *bits = BITS_TO_BYTES(*bits); - return true; + size_t bytes = 0; + if (botan_mp_num_bits(a.mp, &bytes)) { + RNP_LOG("botan_mp_num_bits failed."); } - return false; + return BITS_TO_BYTES(bytes); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/bn.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/bn.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/bn.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/bn.h 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017-2018 Ribose Inc. + * Copyright (c) 2017-2021 Ribose Inc. * Copyright (c) 2012 Alistair Crooks * All rights reserved. * @@ -29,40 +29,36 @@ #include #include +#include "config.h" +#include "mpi.h" -typedef struct botan_mp_struct *botan_mp_t; +#if defined(CRYPTO_BACKEND_OPENSSL) +#include -/* - * bignum_t struct - */ +#define bignum_t BIGNUM +#elif defined(CRYPTO_BACKEND_BOTAN) +typedef struct botan_mp_struct *botan_mp_t; typedef struct bignum_t_st { botan_mp_t mp; } bignum_t; #define BN_HANDLE(x) ((x).mp) #define BN_HANDLE_PTR(x) ((x)->mp) +#else +#error "Unknown crypto backend." +#endif /*********************************/ bignum_t *bn_new(void); void bn_free(bignum_t * /*a*/); -bignum_t *bn_bin2bn(const uint8_t * /*buf*/, int /*size*/, bignum_t * /*bn*/); -int bn_bn2bin(const bignum_t * /*a*/, unsigned char * /*b*/); +int bn_bn2bin(const bignum_t * /*a*/, unsigned char * /*b*/); -/* - * @param a Initialized bignum_t structure - * @param bits [out] bitlength of a - * - * @returns true on success, otherwise false - */ -bool bn_num_bits(const bignum_t *a, size_t *bits); -/* - * @param a Initialized bignum_t structure - * @param bytes [out] byte length of a - * - * @returns true on success, otherwise false - */ -bool bn_num_bytes(const bignum_t *a, size_t *bytes); +bignum_t *mpi2bn(const pgp_mpi_t *val); + +bool bn2mpi(const bignum_t *bn, pgp_mpi_t *val); + +size_t bn_num_bytes(const bignum_t &a); #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/bn_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/bn_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/bn_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/bn_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "bn.h" +#include "logging.h" + +/* store in unsigned [big endian] format */ +int +bn_bn2bin(const bignum_t *a, unsigned char *b) +{ + if (!a || !b) { + return -1; + } + return BN_bn2bin(a, b) >= 0 ? 0 : -1; +} + +bignum_t * +mpi2bn(const pgp_mpi_t *val) +{ + assert(val); + if (!val) { + RNP_LOG("NULL val."); + return NULL; + } + bignum_t *res = bn_new(); + if (!res) { + return NULL; + } + if (!BN_bin2bn(val->mpi, val->len, res)) { + bn_free(res); + res = NULL; + } + return res; +} + +bool +bn2mpi(const bignum_t *bn, pgp_mpi_t *val) +{ + val->len = bn_num_bytes(*bn); + return bn_bn2bin(bn, val->mpi) == 0; +} + +bignum_t * +bn_new(void) +{ + return BN_new(); +} + +void +bn_free(bignum_t *a) +{ + BN_clear_free(a); +} + +size_t +bn_num_bytes(const bignum_t &a) +{ + return (BN_num_bits(&a) + 7) / 8; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_botan.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_botan.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_botan.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_botan.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include "cipher_botan.hpp" +#include "utils.h" +#include "types.h" + +static const id_str_pair cipher_mode_map[] = { + {PGP_CIPHER_MODE_CBC, "CBC"}, + {PGP_CIPHER_MODE_OCB, "OCB"}, + {0, NULL}, +}; + +static const id_str_pair cipher_map[] = { + {PGP_SA_AES_128, "AES-128"}, + {PGP_SA_AES_256, "AES-256"}, + {PGP_SA_IDEA, "IDEA"}, + {0, NULL}, +}; + +Cipher_Botan * +Cipher_Botan::create(pgp_symm_alg_t alg, const std::string &name, bool encrypt) +{ + auto cipher = Botan::Cipher_Mode::create( + name, encrypt ? Botan::Cipher_Dir::ENCRYPTION : Botan::Cipher_Dir::DECRYPTION); + if (!cipher) { + RNP_LOG("Failed to create cipher '%s'", name.c_str()); + return nullptr; + } + return new (std::nothrow) Cipher_Botan(alg, std::move(cipher)); +} + +static std::string +make_name(pgp_symm_alg_t cipher, pgp_cipher_mode_t mode, size_t tag_size, bool disable_padding) +{ + const char *cipher_string = id_str_pair::lookup(cipher_map, cipher, NULL); + const char *mode_string = id_str_pair::lookup(cipher_mode_map, mode, NULL); + if (!cipher_string || !mode_string) { + return ""; + } + try { + std::stringstream ss; + ss << cipher_string << "/" << mode_string; + if (tag_size) { + ss << "(" << tag_size << ")"; + } + if (mode == PGP_CIPHER_MODE_CBC && disable_padding) { + ss << "/NoPadding"; + } + return ss.str(); + } catch (const std::exception &e) { + return ""; + } +} + +std::unique_ptr +Cipher_Botan::encryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding) +{ + return std::unique_ptr( + create(cipher, make_name(cipher, mode, tag_size, disable_padding), true)); +} + +std::unique_ptr +Cipher_Botan::decryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding) +{ + return std::unique_ptr( + create(cipher, make_name(cipher, mode, tag_size, disable_padding), false)); +} + +size_t +Cipher_Botan::update_granularity() const +{ + return m_cipher->update_granularity(); +} + +bool +Cipher_Botan::set_key(const uint8_t *key, size_t key_length) +{ + try { + m_cipher->set_key(key, key_length); + } catch (const std::exception &e) { + RNP_LOG("Failed to set key: %s", e.what()); + return false; + } + return true; +} + +bool +Cipher_Botan::set_iv(const uint8_t *iv, size_t iv_length) +{ + try { + m_cipher->start(iv, iv_length); + m_buf.reserve(this->update_granularity()); + } catch (const std::exception &e) { + RNP_LOG("Failed to set IV: %s", e.what()); + return false; + } + return true; +} + +bool +Cipher_Botan::set_ad(const uint8_t *ad, size_t ad_length) +{ + assert(m_cipher->authenticated()); + try { + dynamic_cast(*m_cipher).set_associated_data(ad, ad_length); + } catch (const std::exception &e) { + RNP_LOG("Failed to set AAD: %s", e.what()); + return false; + } + return true; +} + +bool +Cipher_Botan::update(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) +{ + try { + size_t ud = this->update_granularity(); + m_buf.resize(ud); + + *input_consumed = 0; + *output_written = 0; + while (input_length >= ud && output_length >= ud) { + m_buf.assign(input, input + ud); + size_t written = m_cipher->process(m_buf.data(), ud); + std::copy(m_buf.data(), m_buf.data() + written, output); + input += ud; + output += written; + input_length -= ud; + output_length -= written; + + *output_written += written; + *input_consumed += ud; + } + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; + } + return true; +} + +bool +Cipher_Botan::finish(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) +{ + try { + *input_consumed = 0; + *output_written = 0; + size_t ud = this->update_granularity(); + if (input_length > ud) { + if (!update(output, + output_length, + output_written, + input, + input_length - ud, + input_consumed)) { + return false; + } + input += *input_consumed; + input_length = input_length - *input_consumed; + output += *output_written; + output_length -= *output_written; + } + Botan::secure_vector final_block(input, input + input_length); + m_cipher->finish(final_block); + if (final_block.size() > output_length) { + RNP_LOG("Insufficient buffer"); + return false; + } + std::copy(final_block.begin(), final_block.end(), output); + *output_written += final_block.size(); + *input_consumed += input_length; + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; + } + return true; +} + +Cipher_Botan::Cipher_Botan(pgp_symm_alg_t alg, std::unique_ptr cipher) + : Cipher(alg), m_cipher(std::move(cipher)) +{ +} + +Cipher_Botan::~Cipher_Botan() +{ +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_botan.hpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_botan.hpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_botan.hpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_botan.hpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef RNP_CIPHER_BOTAN_HPP +#define RNP_CIPHER_BOTAN_HPP + +#include "cipher.hpp" +#include +#include + +class Cipher_Botan : public Cipher { + public: + static std::unique_ptr encryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding); + static std::unique_ptr decryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding); + + bool set_key(const uint8_t *key, size_t key_length) override; + bool set_iv(const uint8_t *iv, size_t iv_length) override; + bool set_ad(const uint8_t *ad, size_t ad_length) override; + + size_t update_granularity() const override; + + bool update(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) override; + bool finish(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) override; + virtual ~Cipher_Botan(); + + private: + Cipher_Botan(pgp_symm_alg_t alg, std::unique_ptr cipher); + + std::unique_ptr m_cipher; + std::vector m_buf; + + static Cipher_Botan *create(pgp_symm_alg_t alg, const std::string &name, bool encrypt); +}; + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "config.h" +#include "symmetric.h" +#include "cipher.hpp" + +#if defined(CRYPTO_BACKEND_OPENSSL) +#include "cipher_ossl.hpp" +#elif defined(CRYPTO_BACKEND_BOTAN) +#include "cipher_botan.hpp" +#endif + +std::unique_ptr +Cipher::encryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding) +{ +#if defined(CRYPTO_BACKEND_OPENSSL) + return Cipher_OpenSSL::encryption(cipher, mode, tag_size, disable_padding); +#elif defined(CRYPTO_BACKEND_BOTAN) + return Cipher_Botan::encryption(cipher, mode, tag_size, disable_padding); +#else +#error "Crypto backend not specified" +#endif +} + +std::unique_ptr +Cipher::decryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding) +{ +#if defined(CRYPTO_BACKEND_OPENSSL) + return Cipher_OpenSSL::decryption(cipher, mode, tag_size, disable_padding); +#elif defined(CRYPTO_BACKEND_BOTAN) + return Cipher_Botan::decryption(cipher, mode, tag_size, disable_padding); +#else +#error "Crypto backend not specified" +#endif +} + +Cipher::Cipher(pgp_symm_alg_t alg) : m_alg(alg) +{ +} + +Cipher::~Cipher() +{ +} + +size_t +Cipher::block_size() const +{ + return pgp_block_size(m_alg); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher.hpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher.hpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher.hpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher.hpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef RNP_CIPHER_HPP +#define RNP_CIPHER_HPP + +#include +#include + +// Note: for AEAD modes we append the authentication tag to the ciphertext as in RFC 5116 +class Cipher { + public: + // the tag size should be 0 for non-AEAD and must be non-zero for AEAD modes (no default) + static std::unique_ptr encryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size = 0, + bool disable_padding = false); + static std::unique_ptr decryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size = 0, + bool disable_padding = false); + + virtual bool set_key(const uint8_t *key, size_t key_length) = 0; + virtual bool set_iv(const uint8_t *iv, size_t iv_length) = 0; + // only valid for AEAD modes + virtual bool set_ad(const uint8_t *ad, size_t ad_length) = 0; + + virtual size_t block_size() const; + virtual size_t update_granularity() const = 0; + + // input_length must be a multiple of update_granularity + virtual bool update(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) = 0; + // process final block and perform any padding + virtual bool finish(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) = 0; + + virtual ~Cipher(); + + protected: + Cipher(pgp_symm_alg_t alg); + + pgp_symm_alg_t m_alg; +}; + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_ossl.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include "cipher_ossl.hpp" +#include "utils.h" +#include "types.h" +#include + +static const id_str_pair cipher_mode_map[] = { + {PGP_CIPHER_MODE_CBC, "CBC"}, + {PGP_CIPHER_MODE_OCB, "OCB"}, + {0, NULL}, +}; + +static const id_str_pair cipher_map[] = { + {PGP_SA_AES_128, "AES-128"}, + {PGP_SA_AES_256, "AES-256"}, + {PGP_SA_IDEA, "IDEA"}, + {0, NULL}, +}; + +EVP_CIPHER_CTX * +Cipher_OpenSSL::create(const std::string &name, + bool encrypt, + size_t tag_size, + bool disable_padding) +{ + const EVP_CIPHER *cipher = EVP_get_cipherbyname(name.c_str()); + if (!cipher) { + RNP_LOG("Unsupported cipher: %s", name.c_str()); + return nullptr; + } + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + RNP_LOG("Failed to create cipher context: %lu", ERR_peek_last_error()); + return nullptr; + } + if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encrypt ? 1 : 0) != 1) { + RNP_LOG("Failed to initialize cipher: %lu", ERR_peek_last_error()); + EVP_CIPHER_CTX_free(ctx); + return nullptr; + } + // set tag size + if (encrypt && tag_size) { + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_size, NULL) != 1) { + RNP_LOG("Failed to set AEAD tag length: %lu", ERR_peek_last_error()); + EVP_CIPHER_CTX_free(ctx); + return nullptr; + } + } + if (disable_padding) { + EVP_CIPHER_CTX_set_padding(ctx, 0); + } + return ctx; +} + +static std::string +make_name(pgp_symm_alg_t cipher, pgp_cipher_mode_t mode) +{ + const char *cipher_string = id_str_pair::lookup(cipher_map, cipher, NULL); + const char *mode_string = id_str_pair::lookup(cipher_mode_map, mode, NULL); + if (!cipher_string || !mode_string) { + return ""; + } + return std::string(cipher_string) + "-" + mode_string; +} + +std::unique_ptr +Cipher_OpenSSL::encryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding) +{ + return std::unique_ptr(new (std::nothrow) Cipher_OpenSSL( + cipher, + create(make_name(cipher, mode), true, tag_size, disable_padding), + tag_size, + true)); +} + +std::unique_ptr +Cipher_OpenSSL::decryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding) +{ + return std::unique_ptr(new (std::nothrow) Cipher_OpenSSL( + cipher, + create(make_name(cipher, mode), false, tag_size, disable_padding), + tag_size, + false)); +} + +bool +Cipher_OpenSSL::set_key(const uint8_t *key, size_t key_length) +{ + assert(key_length <= INT_MAX); + return EVP_CIPHER_CTX_set_key_length(m_ctx, (int) key_length) == 1 && + EVP_CipherInit_ex(m_ctx, NULL, NULL, key, NULL, -1) == 1; +} + +bool +Cipher_OpenSSL::set_iv(const uint8_t *iv, size_t iv_length) +{ + assert(iv_length <= INT_MAX); + // set IV len for AEAD modes + if (m_tag_size && + EVP_CIPHER_CTX_ctrl(m_ctx, EVP_CTRL_AEAD_SET_IVLEN, (int) iv_length, NULL) != 1) { + RNP_LOG("Failed to set AEAD IV length: %lu", ERR_peek_last_error()); + return false; + } + if (EVP_CIPHER_CTX_iv_length(m_ctx) != (int) iv_length) { + RNP_LOG("IV length mismatch"); + return false; + } + if (EVP_CipherInit_ex(m_ctx, NULL, NULL, NULL, iv, -1) != 1) { + RNP_LOG("Failed to set IV: %lu", ERR_peek_last_error()); + } + return true; +} + +bool +Cipher_OpenSSL::set_ad(const uint8_t *ad, size_t ad_length) +{ + assert(m_tag_size); + int outlen = 0; + if (EVP_CipherUpdate(m_ctx, NULL, &outlen, ad, ad_length) != 1) { + RNP_LOG("Failed to set AD: %lu", ERR_peek_last_error()); + return false; + } + if ((size_t) outlen != ad_length) { + RNP_LOG("Failed to set AD"); + return false; + } + return true; +} + +size_t +Cipher_OpenSSL::update_granularity() const +{ + return (size_t) EVP_CIPHER_CTX_block_size(m_ctx); +} + +bool +Cipher_OpenSSL::update(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) +{ + if (input_length > INT_MAX) { + return false; + } + *input_consumed = 0; + *output_written = 0; + if (input_length == 0) { + return true; + } + int outl = 0; + if (EVP_CipherUpdate(m_ctx, output, &outl, input, (int) input_length) != 1) { + RNP_LOG("EVP_CipherUpdate failed: %lu", ERR_peek_last_error()); + return false; + } + assert((size_t) outl < output_length); + *input_consumed = input_length; + *output_written = (size_t) outl; + return true; +} + +bool +Cipher_OpenSSL::finish(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) +{ + if (input_length > INT_MAX) { + return false; + } + if (input_length < m_tag_size) { + RNP_LOG("Insufficient input for final block (missing tag)"); + return false; + } + *input_consumed = 0; + *output_written = 0; + if (!m_encrypt && m_tag_size) { + // set the tag from the end of the ciphertext + if (EVP_CIPHER_CTX_ctrl(m_ctx, + EVP_CTRL_AEAD_SET_TAG, + m_tag_size, + const_cast(input) + input_length - m_tag_size) != + 1) { + RNP_LOG("Failed to set expected AEAD tag: %lu", ERR_peek_last_error()); + return false; + } + input_length -= m_tag_size; + *input_consumed += m_tag_size; + } + int outl = 0; + if (EVP_CipherUpdate(m_ctx, output, &outl, input, (int) input_length) != 1) { + RNP_LOG("EVP_CipherUpdate failed: %lu", ERR_peek_last_error()); + return false; + } + input += input_length; + *input_consumed += input_length; + output += outl; + *output_written += (size_t) outl; + if (EVP_CipherFinal_ex(m_ctx, output, &outl) != 1) { + RNP_LOG("EVP_CipherFinal_ex failed: %lu", ERR_peek_last_error()); + return false; + } + *output_written += (size_t) outl; + output += (size_t) outl; + if (m_encrypt && m_tag_size) { + // append the tag + if (EVP_CIPHER_CTX_ctrl(m_ctx, EVP_CTRL_AEAD_GET_TAG, m_tag_size, output) != 1) { + RNP_LOG("Failed to append AEAD tag: %lu", ERR_peek_last_error()); + return false; + } + *output_written += m_tag_size; + } + return true; +} + +Cipher_OpenSSL::Cipher_OpenSSL(pgp_symm_alg_t alg, + EVP_CIPHER_CTX *ctx, + size_t tag_size, + bool encrypt) + : Cipher(alg), m_ctx(ctx), m_tag_size(tag_size), m_encrypt(encrypt) +{ + m_block_size = EVP_CIPHER_CTX_block_size(m_ctx); +} + +Cipher_OpenSSL::~Cipher_OpenSSL() +{ + EVP_CIPHER_CTX_free(m_ctx); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_ossl.hpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_ossl.hpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/cipher_ossl.hpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/cipher_ossl.hpp 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef RNP_CIPHER_OSSL_HPP +#define RNP_CIPHER_OSSL_HPP + +#include "cipher.hpp" +#include +#include + +class Cipher_OpenSSL : public Cipher { + public: + static std::unique_ptr encryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding); + static std::unique_ptr decryption(pgp_symm_alg_t cipher, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding); + + bool set_key(const uint8_t *key, size_t key_length) override; + bool set_iv(const uint8_t *iv, size_t iv_length) override; + bool set_ad(const uint8_t *ad, size_t ad_length) override; + + size_t update_granularity() const override; + + // input_length should not exceed INT_MAX + bool update(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) override; + bool finish(uint8_t * output, + size_t output_length, + size_t * output_written, + const uint8_t *input, + size_t input_length, + size_t * input_consumed) override; + virtual ~Cipher_OpenSSL(); + + private: + Cipher_OpenSSL(pgp_symm_alg_t alg, EVP_CIPHER_CTX *ctx, size_t tag_size, bool encrypt); + + EVP_CIPHER_CTX *m_ctx; + size_t m_block_size; + size_t m_tag_size; + bool m_encrypt; + + static EVP_CIPHER_CTX *create(const std::string &name, + bool encrypt, + size_t tag_size, + bool disable_padding); +}; + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/common.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/common.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/common.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/common.h 2022-04-15 07:49:22.000000000 +0000 @@ -45,5 +45,7 @@ #include "hash.h" /* s2k */ #include "s2k.h" +/* backend name and version */ +#include "backend_version.h" #endif // RNP_CRYPTO_COMMON_H_ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dl_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dl_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dl_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dl_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "bn.h" +#include "dl_ossl.h" +#include "utils.h" +#include +#include +#include + +EVP_PKEY * +dl_load_key(const pgp_mpi_t &mp, + const pgp_mpi_t *mq, + const pgp_mpi_t &mg, + const pgp_mpi_t &my, + const pgp_mpi_t *mx) +{ + DH * dh = NULL; + EVP_PKEY *evpkey = NULL; + bignum_t *p = mpi2bn(&mp); + bignum_t *q = mq ? mpi2bn(mq) : NULL; + bignum_t *g = mpi2bn(&mg); + bignum_t *y = mpi2bn(&my); + bignum_t *x = mx ? mpi2bn(mx) : NULL; + + if (!p || (mq && !q) || !g || !y || (mx && !x)) { + RNP_LOG("out of memory"); + goto done; + } + + dh = DH_new(); + if (!dh) { + RNP_LOG("out of memory"); + goto done; + } + int res; + /* line below must not fail */ + res = DH_set0_pqg(dh, p, q, g); + assert(res == 1); + if (res < 1) { + goto done; + } + p = NULL; + q = NULL; + g = NULL; + /* line below must not fail */ + res = DH_set0_key(dh, y, x); + assert(res == 1); + if (res < 1) { + goto done; + } + y = NULL; + x = NULL; + + evpkey = EVP_PKEY_new(); + if (!evpkey) { + RNP_LOG("allocation failed"); + goto done; + } + if (EVP_PKEY_set1_DH(evpkey, dh) <= 0) { + RNP_LOG("Failed to set key: %lu", ERR_peek_last_error()); + EVP_PKEY_free(evpkey); + evpkey = NULL; + } +done: + DH_free(dh); + bn_free(p); + bn_free(q); + bn_free(g); + bn_free(y); + bn_free(x); + return evpkey; +} + +static rnp_result_t +dl_validate_secret_key(EVP_PKEY *dlkey, const pgp_mpi_t &mx) +{ + DH *dh = EVP_PKEY_get0_DH(dlkey); + assert(dh); + const bignum_t *p = DH_get0_p(dh); + const bignum_t *q = DH_get0_q(dh); + const bignum_t *g = DH_get0_g(dh); + const bignum_t *y = DH_get0_pub_key(dh); + assert(p && g && y); + bignum_t *p1 = NULL; + + rnp_result_t ret = RNP_ERROR_GENERIC; + + BN_CTX * ctx = BN_CTX_new(); + bignum_t *x = mpi2bn(&mx); + bignum_t *cy = bn_new(); + + if (!x || !cy || !ctx) { + RNP_LOG("Allocation failed"); + goto done; + } + if (!q) { + /* if q is NULL then group order is (p - 1) / 2 */ + p1 = BN_dup(p); + if (!p1) { + RNP_LOG("Allocation failed"); + goto done; + } + int res; + res = BN_rshift(p1, p1, 1); + assert(res == 1); + if (res < 1) { + RNP_LOG("BN_rshift failed."); + goto done; + } + q = p1; + } + if (BN_cmp(x, q) != -1) { + RNP_LOG("x is too large."); + goto done; + } + if (BN_mod_exp_mont_consttime(cy, g, x, p, ctx, NULL) < 1) { + RNP_LOG("Exponentiation failed"); + goto done; + } + if (BN_cmp(cy, y) == 0) { + ret = RNP_SUCCESS; + } +done: + BN_CTX_free(ctx); + bn_free(x); + bn_free(cy); + bn_free(p1); + return ret; +} + +rnp_result_t +dl_validate_key(EVP_PKEY *pkey, const pgp_mpi_t *x) +{ + rnp_result_t ret = RNP_ERROR_GENERIC; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + goto done; + } + int res; + res = EVP_PKEY_param_check(ctx); + if (res < 0) { + RNP_LOG("Param validation error: %lu (%s)", + ERR_peek_last_error(), + ERR_reason_error_string(ERR_peek_last_error())); + } + if (res < 1) { + /* ElGamal specification doesn't seem to restrict P to the safe prime */ + auto err = ERR_peek_last_error(); + DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME); + if ((ERR_GET_FUNC(err) == DH_F_DH_CHECK_EX) && + (ERR_GET_REASON(err) == DH_R_CHECK_P_NOT_SAFE_PRIME)) { + RNP_LOG("Warning! P is not a safe prime."); + } else { + goto done; + } + } + res = EVP_PKEY_public_check(ctx); + if (res < 0) { + RNP_LOG("Key validation error: %lu", ERR_peek_last_error()); + } + if (res < 1) { + goto done; + } + /* There is no private key check in OpenSSL yet, so need to check x vs y manually */ + if (!x) { + ret = RNP_SUCCESS; + goto done; + } + ret = dl_validate_secret_key(pkey, *x); +done: + EVP_PKEY_CTX_free(ctx); + return ret; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dl_ossl.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dl_ossl.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dl_ossl.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dl_ossl.h 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DL_OSSL_H_ +#define DL_OSSL_H_ + +#include "types.h" +#include "config.h" +#include +#include "mpi.h" +#include + +EVP_PKEY *dl_load_key(const pgp_mpi_t &mp, + const pgp_mpi_t *mq, + const pgp_mpi_t &mg, + const pgp_mpi_t &my, + const pgp_mpi_t *mx); + +rnp_result_t dl_validate_key(EVP_PKEY *pkey, const pgp_mpi_t *mx); + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dsa.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dsa.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dsa.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dsa.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -81,12 +81,13 @@ #include #include "dsa.h" #include "hash.h" +#include "bn.h" #include "utils.h" #define DSA_MAX_Q_BITLEN 256 rnp_result_t -dsa_validate_key(rng_t *rng, const pgp_dsa_key_t *key, bool secret) +dsa_validate_key(rnp::RNG *rng, const pgp_dsa_key_t *key, bool secret) { bignum_t * p = NULL; bignum_t * q = NULL; @@ -114,7 +115,7 @@ goto done; } - if (botan_pubkey_check_key(bpkey, rng_handle(rng), 0)) { + if (botan_pubkey_check_key(bpkey, rng->handle(), 0)) { goto done; } @@ -135,7 +136,7 @@ goto done; } - if (botan_privkey_check_key(bskey, rng_handle(rng), 0)) { + if (botan_privkey_check_key(bskey, rng->handle(), 0)) { goto done; } @@ -152,7 +153,7 @@ } rnp_result_t -dsa_sign(rng_t * rng, +dsa_sign(rnp::RNG * rng, pgp_dsa_signature_t *sig, const uint8_t * hash, size_t hash_len, @@ -203,7 +204,7 @@ goto end; } - if (botan_pk_op_sign_finish(sign_op, rng_handle(rng), sign_buf, &sigbuf_size)) { + if (botan_pk_op_sign_finish(sign_op, rng->handle(), sign_buf, &sigbuf_size)) { RNP_LOG("Signing has failed"); goto end; } @@ -298,7 +299,7 @@ } rnp_result_t -dsa_generate(rng_t *rng, pgp_dsa_key_t *key, size_t keylen, size_t qbits) +dsa_generate(rnp::RNG *rng, pgp_dsa_key_t *key, size_t keylen, size_t qbits) { if ((keylen < 1024) || (keylen > 3072) || (qbits < 160) || (qbits > 256)) { return RNP_ERROR_BAD_PARAMETERS; @@ -318,8 +319,8 @@ goto end; } - if (botan_privkey_create_dsa(&key_priv, rng_handle(rng), keylen, qbits) || - botan_privkey_check_key(key_priv, rng_handle(rng), 1) || + if (botan_privkey_create_dsa(&key_priv, rng->handle(), keylen, qbits) || + botan_privkey_check_key(key_priv, rng->handle(), 1) || botan_privkey_export_pubkey(&key_pub, key_priv)) { RNP_LOG("Wrong parameters"); ret = RNP_ERROR_BAD_PARAMETERS; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dsa.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dsa.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dsa.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dsa.h 2022-04-15 07:49:22.000000000 +0000 @@ -59,7 +59,7 @@ * * @return RNP_SUCCESS if key is valid or error code otherwise */ -rnp_result_t dsa_validate_key(rng_t *rng, const pgp_dsa_key_t *key, bool secret); +rnp_result_t dsa_validate_key(rnp::RNG *rng, const pgp_dsa_key_t *key, bool secret); /* * @brief Performs DSA signing @@ -74,7 +74,7 @@ * RNP_ERROR_BAD_PARAMETERS wrong input provided * RNP_ERROR_SIGNING_FAILED internal error */ -rnp_result_t dsa_sign(rng_t * rng, +rnp_result_t dsa_sign(rnp::RNG * rng, pgp_dsa_signature_t *sig, const uint8_t * hash, size_t hash_len, @@ -112,7 +112,7 @@ * RNP_ERROR_GENERIC internal error * RNP_ERROR_SIGNATURE_INVALID signature is invalid */ -rnp_result_t dsa_generate(rng_t *rng, pgp_dsa_key_t *key, size_t keylen, size_t qbits); +rnp_result_t dsa_generate(rnp::RNG *rng, pgp_dsa_key_t *key, size_t keylen, size_t qbits); /* * @brief Returns minimally sized hash which will work diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dsa_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dsa_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/dsa_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/dsa_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "bn.h" +#include "dsa.h" +#include "dl_ossl.h" +#include "hash.h" +#include "utils.h" +#include +#include +#include +#include + +#define DSA_MAX_Q_BITLEN 256 + +static bool +dsa_decode_sig(const uint8_t *data, size_t len, pgp_dsa_signature_t &sig) +{ + DSA_SIG *dsig = d2i_DSA_SIG(NULL, &data, len); + if (!dsig) { + RNP_LOG("Failed to parse DSA sig: %lu", ERR_peek_last_error()); + return false; + } + const BIGNUM *r, *s; + DSA_SIG_get0(dsig, &r, &s); + bn2mpi(r, &sig.r); + bn2mpi(s, &sig.s); + DSA_SIG_free(dsig); + return true; +} + +static bool +dsa_encode_sig(uint8_t *data, size_t *len, const pgp_dsa_signature_t &sig) +{ + bool res = false; + DSA_SIG *dsig = DSA_SIG_new(); + BIGNUM * r = mpi2bn(&sig.r); + BIGNUM * s = mpi2bn(&sig.s); + if (!dsig || !r || !s) { + RNP_LOG("Allocation failed."); + goto done; + } + DSA_SIG_set0(dsig, r, s); + r = NULL; + s = NULL; + int outlen; + outlen = i2d_DSA_SIG(dsig, &data); + if (outlen < 0) { + RNP_LOG("Failed to encode signature."); + goto done; + } + *len = outlen; + res = true; +done: + DSA_SIG_free(dsig); + BN_free(r); + BN_free(s); + return res; +} + +static EVP_PKEY * +dsa_load_key(const pgp_dsa_key_t *key, bool secret = false) +{ + DSA * dsa = NULL; + EVP_PKEY *evpkey = NULL; + bignum_t *p = mpi2bn(&key->p); + bignum_t *q = mpi2bn(&key->q); + bignum_t *g = mpi2bn(&key->g); + bignum_t *y = mpi2bn(&key->y); + bignum_t *x = secret ? mpi2bn(&key->x) : NULL; + + if (!p || !q || !g || !y || (secret && !x)) { + RNP_LOG("out of memory"); + goto done; + } + + dsa = DSA_new(); + if (!dsa) { + RNP_LOG("Out of memory"); + goto done; + } + if (DSA_set0_pqg(dsa, p, q, g) != 1) { + RNP_LOG("Failed to set pqg. Error: %lu", ERR_peek_last_error()); + goto done; + } + p = NULL; + q = NULL; + g = NULL; + if (DSA_set0_key(dsa, y, x) != 1) { + RNP_LOG("Secret key load error: %lu", ERR_peek_last_error()); + goto done; + } + y = NULL; + x = NULL; + + evpkey = EVP_PKEY_new(); + if (!evpkey) { + RNP_LOG("allocation failed"); + goto done; + } + if (EVP_PKEY_set1_DSA(evpkey, dsa) <= 0) { + RNP_LOG("Failed to set key: %lu", ERR_peek_last_error()); + EVP_PKEY_free(evpkey); + evpkey = NULL; + } +done: + DSA_free(dsa); + bn_free(p); + bn_free(q); + bn_free(g); + bn_free(y); + bn_free(x); + return evpkey; +} + +rnp_result_t +dsa_validate_key(rnp::RNG *rng, const pgp_dsa_key_t *key, bool secret) +{ + /* OpenSSL doesn't implement key checks for the DSA, however we may use DL via DH */ + EVP_PKEY *pkey = dl_load_key(key->p, &key->q, key->g, key->y, NULL); + if (!pkey) { + RNP_LOG("Failed to load key"); + return RNP_ERROR_BAD_PARAMETERS; + } + rnp_result_t ret = dl_validate_key(pkey, secret ? &key->x : NULL); + EVP_PKEY_free(pkey); + return ret; +} + +rnp_result_t +dsa_sign(rnp::RNG * rng, + pgp_dsa_signature_t *sig, + const uint8_t * hash, + size_t hash_len, + const pgp_dsa_key_t *key) +{ + if (mpi_bytes(&key->x) == 0) { + RNP_LOG("private key not set"); + return RNP_ERROR_BAD_PARAMETERS; + } + + /* Load secret key to DSA structure*/ + EVP_PKEY *evpkey = dsa_load_key(key, true); + if (!evpkey) { + RNP_LOG("Failed to load key"); + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_GENERIC; + /* init context and sign */ + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(evpkey, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_sign_init(ctx) <= 0) { + RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); + goto done; + } + sig->s.len = PGP_MPINT_SIZE; + if (EVP_PKEY_sign(ctx, sig->s.mpi, &sig->s.len, hash, hash_len) <= 0) { + RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); + sig->s.len = 0; + goto done; + } + if (!dsa_decode_sig(&sig->s.mpi[0], sig->s.len, *sig)) { + RNP_LOG("Failed to parse DSA sig: %lu", ERR_peek_last_error()); + goto done; + } + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(evpkey); + return ret; +} + +rnp_result_t +dsa_verify(const pgp_dsa_signature_t *sig, + const uint8_t * hash, + size_t hash_len, + const pgp_dsa_key_t * key) +{ + /* Load secret key to DSA structure*/ + EVP_PKEY *evpkey = dsa_load_key(key, false); + if (!evpkey) { + RNP_LOG("Failed to load key"); + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_GENERIC; + /* init context and sign */ + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(evpkey, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_verify_init(ctx) <= 0) { + RNP_LOG("Failed to initialize verify: %lu", ERR_peek_last_error()); + goto done; + } + pgp_mpi_t sigbuf; + if (!dsa_encode_sig(sigbuf.mpi, &sigbuf.len, *sig)) { + goto done; + } + if (EVP_PKEY_verify(ctx, sigbuf.mpi, sigbuf.len, hash, hash_len) <= 0) { + ret = RNP_ERROR_SIGNATURE_INVALID; + } else { + ret = RNP_SUCCESS; + } +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(evpkey); + return ret; +} + +rnp_result_t +dsa_generate(rnp::RNG *rng, pgp_dsa_key_t *key, size_t keylen, size_t qbits) +{ + if ((keylen < 1024) || (keylen > 3072) || (qbits < 160) || (qbits > 256)) { + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_GENERIC; + DSA * dsa = NULL; + EVP_PKEY * pkey = NULL; + EVP_PKEY * parmkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + + /* Generate DSA params */ + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL); + if (!ctx) { + RNP_LOG("Failed to create ctx: %lu", ERR_peek_last_error()); + return ret; + } + if (EVP_PKEY_paramgen_init(ctx) <= 0) { + RNP_LOG("Failed to init keygen: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, keylen) <= 0) { + RNP_LOG("Failed to set key bits: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits) <= 0) { + RNP_LOG("Failed to set key qbits: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_paramgen(ctx, &parmkey) <= 0) { + RNP_LOG("Failed to generate parameters: %lu", ERR_peek_last_error()); + goto done; + } + EVP_PKEY_CTX_free(ctx); + /* Generate DSA key */ + ctx = EVP_PKEY_CTX_new(parmkey, NULL); + if (!ctx) { + RNP_LOG("Failed to create ctx: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_keygen_init(ctx) <= 0) { + RNP_LOG("Failed to init keygen: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + RNP_LOG("DSA keygen failed: %lu", ERR_peek_last_error()); + goto done; + } + dsa = EVP_PKEY_get0_DSA(pkey); + if (!dsa) { + RNP_LOG("Failed to retrieve DSA key: %lu", ERR_peek_last_error()); + goto done; + } + + const bignum_t *p; + const bignum_t *q; + const bignum_t *g; + const bignum_t *y; + const bignum_t *x; + p = DSA_get0_p(dsa); + q = DSA_get0_q(dsa); + g = DSA_get0_g(dsa); + y = DSA_get0_pub_key(dsa); + x = DSA_get0_priv_key(dsa); + if (!p || !q || !g || !y || !x) { + ret = RNP_ERROR_BAD_STATE; + goto done; + } + bn2mpi(p, &key->p); + bn2mpi(q, &key->q); + bn2mpi(g, &key->g); + bn2mpi(y, &key->y); + bn2mpi(x, &key->x); + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(parmkey); + EVP_PKEY_free(pkey); + return ret; +} + +pgp_hash_alg_t +dsa_get_min_hash(size_t qsize) +{ + /* + * I'm using _broken_ SHA1 here only because + * some old implementations may not understand keys created + * with other hashes. If you're sure we don't have to support + * such implementations, please be my guest and remove it. + */ + return (qsize < 160) ? PGP_HASH_UNKNOWN : + (qsize == 160) ? PGP_HASH_SHA1 : + (qsize <= 224) ? PGP_HASH_SHA224 : + (qsize <= 256) ? PGP_HASH_SHA256 : + (qsize <= 384) ? PGP_HASH_SHA384 : + (qsize <= 512) ? PGP_HASH_SHA512 + /*(qsize>512)*/ : + PGP_HASH_UNKNOWN; +} + +size_t +dsa_choose_qsize_by_psize(size_t psize) +{ + return (psize == 1024) ? 160 : + (psize <= 2047) ? 224 : + (psize <= 3072) ? DSA_MAX_Q_BITLEN : + 0; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -26,219 +26,22 @@ #include #include +#include #include "ec.h" #include "types.h" #include "utils.h" #include "mem.h" +#include "bn.h" -/** - * EC Curves definition used by implementation - * - * \see RFC4880 bis01 - 9.2. ECC Curve OID - * - * Order of the elements in this array corresponds to - * values in pgp_curve_t enum. - */ -static const ec_curve_desc_t ec_curves[] = { - {PGP_CURVE_UNKNOWN, 0, {0}, 0, NULL, NULL}, - - {PGP_CURVE_NIST_P_256, - 256, - {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}, - 8, - "secp256r1", - "NIST P-256", - "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", - "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", - "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", - "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", - "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", - "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", - "0x01"}, - {PGP_CURVE_NIST_P_384, - 384, - {0x2B, 0x81, 0x04, 0x00, 0x22}, - 5, - "secp384r1", - "NIST P-384", - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000" - "ffffffff", - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000" - "fffffffc", - "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8ed" - "d3ec2aef", - "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196a" - "ccc52973", - "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e38" - "72760ab7", - "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c" - "90ea0e5f", - "0x01"}, - {PGP_CURVE_NIST_P_521, - 521, - {0x2B, 0x81, 0x04, 0x00, 0x23}, - 5, - "secp521r1", - "NIST P-521", - "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffff", - "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "fffffffffffffffffffffffffffffffffffffffffffc", - "0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652" - "c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", - "0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc" - "0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", - "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1d" - "c127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", - "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550" - "b9013fad0761353c7086a272c24088be94769fd16650", - "0x01"}, - {PGP_CURVE_ED25519, - 255, - {0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01}, - 9, - "Ed25519", - "Ed25519", - "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", - /* two below are actually negative */ - "0x01", - "0x2dfc9311d490018c7338bf8688861767ff8ff5b2bebe27548a14b235eca6874a", - "0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", - "0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a", - "0x6666666666666666666666666666666666666666666666666666666666666658", - "0x08"}, - {PGP_CURVE_25519, - 255, - {0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}, - 10, - "curve25519", - "Curve25519", - "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", - "0x01db41", - "0x01", - "0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", - "0x0000000000000000000000000000000000000000000000000000000000000009", - "0x20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9", - "0x08"}, - {PGP_CURVE_BP256, - 256, - {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}, - 9, - "brainpool256r1", - "brainpoolP256r1", - "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", - "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", - "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", - "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7", - "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262", - "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997", - "0x01"}, - {PGP_CURVE_BP384, - 384, - {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}, - 9, - "brainpool384r1", - "brainpoolP384r1", - "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a7187470013" - "3107ec53", - "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f8aa5814a503ad4eb04a8c7dd" - "22ce2826", - "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d57cb4390295dbc9943ab78696" - "fa504c11", - "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202" - "e9046565", - "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8e826e03436d646aaef87b2e2" - "47d4af1e", - "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341" - "263c5315", - "0x01"}, - {PGP_CURVE_BP512, - 512, - {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}, - 9, - "brainpool512r1", - "brainpoolP512r1", - "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12a" - "e6a380e62881ff2f2d82c68528aa6056583a48f3", - "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c9" - "8b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca", - "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca" - "dc083e67984050b75ebae5dd2809bd638016f723", - "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca9261941866119" - "7fac10471db1d381085ddaddb58796829ca90069", - "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098eff3b1f78e2d0d48d50d1687b" - "93b97d5f7c6d5047406a5e688b352209bcb9f822", - "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111b2dcde494a5f485e5bca4bd8" - "8a2763aed1ca2b2fa8f0540678cd1e0f3ad80892", - "0x01"}, - {PGP_CURVE_P256K1, - 256, - {0x2B, 0x81, 0x04, 0x00, 0x0A}, - 5, - "secp256k1", - "secp256k1", - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000007", - "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "0x01"}, - { - PGP_CURVE_SM2_P_256, - 256, - {0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D}, - 8, - "sm2p256v1", - "SM2 P-256", - "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", - "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", - "0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", - "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", - "0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", - "0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", - }, -}; - -static pgp_map_t ec_algo_to_botan[] = { +static id_str_pair ec_algo_to_botan[] = { {PGP_PKA_ECDH, "ECDH"}, {PGP_PKA_ECDSA, "ECDSA"}, {PGP_PKA_SM2, "SM2_Sig"}, + {0, NULL}, }; -pgp_curve_t -find_curve_by_OID(const uint8_t *oid, size_t oid_len) -{ - for (size_t i = 0; i < PGP_CURVE_MAX; i++) { - if ((oid_len == ec_curves[i].OIDhex_len) && - (!memcmp(oid, ec_curves[i].OIDhex, oid_len))) { - return static_cast(i); - } - } - - return PGP_CURVE_MAX; -} - -pgp_curve_t -find_curve_by_name(const char *name) -{ - for (size_t i = 1; i < PGP_CURVE_MAX; i++) { - if (!rnp_strcasecmp(ec_curves[i].pgp_name, name)) { - return ec_curves[i].rnp_curve_id; - } - } - - return PGP_CURVE_MAX; -} - -const ec_curve_desc_t * -get_curve_desc(const pgp_curve_t curve_id) -{ - return (curve_id < PGP_CURVE_MAX && curve_id > 0) ? &ec_curves[curve_id] : NULL; -} - rnp_result_t -x25519_generate(rng_t *rng, pgp_ec_key_t *key) +x25519_generate(rnp::RNG *rng, pgp_ec_key_t *key) { botan_privkey_t pr_key = NULL; botan_pubkey_t pu_key = NULL; @@ -246,7 +49,7 @@ rnp::secure_array keyle; - if (botan_privkey_create(&pr_key, "Curve25519", "", rng_handle(rng))) { + if (botan_privkey_create(&pr_key, "Curve25519", "", rng->handle())) { goto end; } @@ -262,6 +65,10 @@ key->x.mpi[31 - i] = keyle[i]; } key->x.len = 32; + /* botan doesn't tweak secret key bits, so we should do that here */ + if (!x25519_tweak_bits(*key)) { + goto end; + } if (botan_pubkey_x25519_get_pubkey(pu_key, &key->p.mpi[1])) { goto end; @@ -276,27 +83,8 @@ return ret; } -static bool -alg_allows_curve(pgp_pubkey_alg_t alg, pgp_curve_t curve) -{ - /* SM2 curve is only for SM2 algo */ - if ((alg == PGP_PKA_SM2) || (curve == PGP_CURVE_SM2_P_256)) { - return (alg == PGP_PKA_SM2) && (curve == PGP_CURVE_SM2_P_256); - } - /* EDDSA and PGP_CURVE_ED25519 */ - if ((alg == PGP_PKA_EDDSA) || (curve == PGP_CURVE_ED25519)) { - return (alg == PGP_PKA_EDDSA) && (curve == PGP_CURVE_ED25519); - } - /* Curve x25519 is only for ECDH */ - if (curve == PGP_CURVE_25519) { - return alg == PGP_PKA_ECDH; - } - /* Other curves are good for both ECDH and ECDSA */ - return true; -} - rnp_result_t -ec_generate(rng_t * rng, +ec_generate(rnp::RNG * rng, pgp_ec_key_t * key, const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) @@ -319,6 +107,8 @@ return RNP_ERROR_BAD_PARAMETERS; } + const char *ec_algo = id_str_pair::lookup(ec_algo_to_botan, alg_id, NULL); + assert(ec_algo); const ec_curve_desc_t *ec_desc = get_curve_desc(curve); if (!ec_desc) { ret = RNP_ERROR_BAD_PARAMETERS; @@ -327,10 +117,7 @@ filed_byte_size = BITS_TO_BYTES(ec_desc->bitlen); // at this point it must succeed - if (botan_privkey_create(&pr_key, - pgp_str_from_map(alg_id, ec_algo_to_botan), - ec_desc->botan_name, - rng_handle(rng))) { + if (botan_privkey_create(&pr_key, ec_algo, ec_desc->botan_name, rng->handle())) { goto end; } @@ -363,8 +150,8 @@ size_t x_bytes; size_t y_bytes; - (void) bn_num_bytes(px, &x_bytes); // Can't fail - (void) bn_num_bytes(py, &y_bytes); + x_bytes = bn_num_bytes(*px); + y_bytes = bn_num_bytes(*py); // Safety check if ((x_bytes > filed_byte_size) || (y_bytes > filed_byte_size)) { diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec_curves.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec_curves.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec_curves.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec_curves.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "ec.h" +#include "types.h" +#include "utils.h" +#include "str-utils.h" + +/** + * EC Curves definition used by implementation + * + * \see RFC4880 bis01 - 9.2. ECC Curve OID + * + * Order of the elements in this array corresponds to + * values in pgp_curve_t enum. + */ +static const ec_curve_desc_t ec_curves[] = { + {PGP_CURVE_UNKNOWN, 0, {0}, 0, NULL, NULL}, + + {PGP_CURVE_NIST_P_256, + 256, + {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}, + 8, +#if defined(CRYPTO_BACKEND_BOTAN) + "secp256r1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "prime256v1", +#endif + "NIST P-256", + true, + "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", + "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "0x01"}, + {PGP_CURVE_NIST_P_384, + 384, + {0x2B, 0x81, 0x04, 0x00, 0x22}, + 5, +#if defined(CRYPTO_BACKEND_BOTAN) + "secp384r1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "secp384r1", +#endif + "NIST P-384", + true, + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000" + "ffffffff", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000" + "fffffffc", + "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8ed" + "d3ec2aef", + "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196a" + "ccc52973", + "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e38" + "72760ab7", + "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c" + "90ea0e5f", + "0x01"}, + {PGP_CURVE_NIST_P_521, + 521, + {0x2B, 0x81, 0x04, 0x00, 0x23}, + 5, +#if defined(CRYPTO_BACKEND_BOTAN) + "secp521r1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "secp521r1", +#endif + "NIST P-521", + true, + "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffff", + "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffc", + "0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652" + "c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", + "0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc" + "0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", + "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1d" + "c127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", + "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550" + "b9013fad0761353c7086a272c24088be94769fd16650", + "0x01"}, + {PGP_CURVE_ED25519, + 255, + {0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01}, + 9, +#if defined(CRYPTO_BACKEND_BOTAN) + "Ed25519", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "ED25519", +#endif + "Ed25519", + true, + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", + /* two below are actually negative */ + "0x01", + "0x2dfc9311d490018c7338bf8688861767ff8ff5b2bebe27548a14b235eca6874a", + "0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", + "0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a", + "0x6666666666666666666666666666666666666666666666666666666666666658", + "0x08"}, + {PGP_CURVE_25519, + 255, + {0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}, + 10, +#if defined(CRYPTO_BACKEND_BOTAN) + "curve25519", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "X25519", +#endif + "Curve25519", + true, + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", + "0x01db41", + "0x01", + "0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9", + "0x08"}, + {PGP_CURVE_BP256, + 256, + {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}, + 9, +#if defined(CRYPTO_BACKEND_BOTAN) + "brainpool256r1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "brainpoolP256r1", +#endif + "brainpoolP256r1", +#if defined(ENABLE_BRAINPOOL) + true, +#else + false, +#endif + "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", + "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", + "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", + "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7", + "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262", + "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997", + "0x01"}, + {PGP_CURVE_BP384, + 384, + {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}, + 9, +#if defined(CRYPTO_BACKEND_BOTAN) + "brainpool384r1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "brainpoolP384r1", +#endif + "brainpoolP384r1", +#if defined(ENABLE_BRAINPOOL) + true, +#else + false, +#endif + "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a7187470013" + "3107ec53", + "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f8aa5814a503ad4eb04a8c7dd" + "22ce2826", + "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d57cb4390295dbc9943ab78696" + "fa504c11", + "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202" + "e9046565", + "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8e826e03436d646aaef87b2e2" + "47d4af1e", + "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341" + "263c5315", + "0x01"}, + {PGP_CURVE_BP512, + 512, + {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}, + 9, +#if defined(CRYPTO_BACKEND_BOTAN) + "brainpool512r1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "brainpoolP512r1", +#endif + "brainpoolP512r1", +#if defined(ENABLE_BRAINPOOL) + true, +#else + false, +#endif + "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12a" + "e6a380e62881ff2f2d82c68528aa6056583a48f3", + "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c9" + "8b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca", + "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca" + "dc083e67984050b75ebae5dd2809bd638016f723", + "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca9261941866119" + "7fac10471db1d381085ddaddb58796829ca90069", + "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098eff3b1f78e2d0d48d50d1687b" + "93b97d5f7c6d5047406a5e688b352209bcb9f822", + "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111b2dcde494a5f485e5bca4bd8" + "8a2763aed1ca2b2fa8f0540678cd1e0f3ad80892", + "0x01"}, + {PGP_CURVE_P256K1, + 256, + {0x2B, 0x81, 0x04, 0x00, 0x0A}, + 5, +#if defined(CRYPTO_BACKEND_BOTAN) + "secp256k1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "secp256k1", +#endif + "secp256k1", + true, + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "0x01"}, + { + PGP_CURVE_SM2_P_256, + 256, + {0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D}, + 8, +#if defined(CRYPTO_BACKEND_BOTAN) + "sm2p256v1", +#elif defined(CRYPTO_BACKEND_OPENSSL) + "sm2", +#endif + "SM2 P-256", +#if defined(ENABLE_SM2) + true, +#else + false, +#endif + "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", + "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", + "0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", + "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", + "0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", + "0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", + }, +}; + +pgp_curve_t +find_curve_by_OID(const uint8_t *oid, size_t oid_len) +{ + for (size_t i = 0; i < PGP_CURVE_MAX; i++) { + if ((oid_len == ec_curves[i].OIDhex_len) && + (!memcmp(oid, ec_curves[i].OIDhex, oid_len))) { + return static_cast(i); + } + } + + return PGP_CURVE_MAX; +} + +pgp_curve_t +find_curve_by_name(const char *name) +{ + for (size_t i = 1; i < PGP_CURVE_MAX; i++) { + if (rnp::str_case_eq(ec_curves[i].pgp_name, name)) { + return ec_curves[i].rnp_curve_id; + } + } + + return PGP_CURVE_MAX; +} + +const ec_curve_desc_t * +get_curve_desc(const pgp_curve_t curve_id) +{ + return (curve_id < PGP_CURVE_MAX && curve_id > 0) ? &ec_curves[curve_id] : NULL; +} + +bool +alg_allows_curve(pgp_pubkey_alg_t alg, pgp_curve_t curve) +{ + /* SM2 curve is only for SM2 algo */ + if ((alg == PGP_PKA_SM2) || (curve == PGP_CURVE_SM2_P_256)) { + return (alg == PGP_PKA_SM2) && (curve == PGP_CURVE_SM2_P_256); + } + /* EDDSA and PGP_CURVE_ED25519 */ + if ((alg == PGP_PKA_EDDSA) || (curve == PGP_CURVE_ED25519)) { + return (alg == PGP_PKA_EDDSA) && (curve == PGP_CURVE_ED25519); + } + /* Curve x25519 is only for ECDH */ + if (curve == PGP_CURVE_25519) { + return alg == PGP_PKA_ECDH; + } + /* Other curves are good for both ECDH and ECDSA */ + return true; +} + +bool +curve_supported(pgp_curve_t curve) +{ + const ec_curve_desc_t *info = get_curve_desc(curve); + return info && info->supported; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -27,120 +27,13 @@ #include #include #include "ecdh.h" +#include "ecdh_utils.h" #include "hash.h" #include "symmetric.h" #include "types.h" #include "utils.h" #include "mem.h" - -#define MAX_SP800_56A_OTHER_INFO 56 -// Keys up to 312 bits (+1 bytes of PKCS5 padding) -#define MAX_SESSION_KEY_SIZE 40 - -/* Used by ECDH keys. Specifies which hash and wrapping algorithm - * to be used (see point 15. of RFC 4880). - * - * Note: sync with ec_curves. - */ -static const struct ecdh_params_t { - pgp_curve_t curve; /* Curve ID */ - pgp_hash_alg_t hash; /* Hash used by kdf */ - pgp_symm_alg_t wrap_alg; /* Symmetric algorithm used to wrap KEK*/ -} ecdh_params[] = { - {.curve = PGP_CURVE_NIST_P_256, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, - {.curve = PGP_CURVE_NIST_P_384, .hash = PGP_HASH_SHA384, .wrap_alg = PGP_SA_AES_192}, - {.curve = PGP_CURVE_NIST_P_521, .hash = PGP_HASH_SHA512, .wrap_alg = PGP_SA_AES_256}, - {.curve = PGP_CURVE_BP256, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, - {.curve = PGP_CURVE_BP384, .hash = PGP_HASH_SHA384, .wrap_alg = PGP_SA_AES_192}, - {.curve = PGP_CURVE_BP512, .hash = PGP_HASH_SHA512, .wrap_alg = PGP_SA_AES_256}, - {.curve = PGP_CURVE_25519, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, - {.curve = PGP_CURVE_P256K1, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, -}; - -// "Anonymous Sender " in hex -static const unsigned char ANONYMOUS_SENDER[] = {0x41, 0x6E, 0x6F, 0x6E, 0x79, 0x6D, 0x6F, - 0x75, 0x73, 0x20, 0x53, 0x65, 0x6E, 0x64, - 0x65, 0x72, 0x20, 0x20, 0x20, 0x20}; - -// returns size of data written to other_info -static size_t -kdf_other_info_serialize(uint8_t other_info[MAX_SP800_56A_OTHER_INFO], - const ec_curve_desc_t * ec_curve, - const pgp_fingerprint_t &fingerprint, - const pgp_hash_alg_t kdf_hash, - const pgp_symm_alg_t wrap_alg) -{ - if (fingerprint.length < 20) { - RNP_LOG("Implementation error: unexpected fingerprint length"); - return false; - } - - uint8_t *buf_ptr = &other_info[0]; - - /* KDF-OtherInfo: AlgorithmID - * Current implementation will always use SHA-512 and AES-256 for KEK wrapping - */ - *(buf_ptr++) = ec_curve->OIDhex_len; - memcpy(buf_ptr, ec_curve->OIDhex, ec_curve->OIDhex_len); - buf_ptr += ec_curve->OIDhex_len; - *(buf_ptr++) = PGP_PKA_ECDH; - // size of following 3 params (each 1 byte) - *(buf_ptr++) = 0x03; - // Value reserved for future use - *(buf_ptr++) = 0x01; - // Hash used with KDF - *(buf_ptr++) = kdf_hash; - // Algorithm ID used for key wrapping - *(buf_ptr++) = wrap_alg; - - /* KDF-OtherInfo: PartyUInfo - * 20 bytes representing "Anonymous Sender " - */ - memcpy(buf_ptr, ANONYMOUS_SENDER, sizeof(ANONYMOUS_SENDER)); - - buf_ptr += sizeof(ANONYMOUS_SENDER); - - // keep 20, as per spec - memcpy(buf_ptr, fingerprint.fingerprint, 20); - return (buf_ptr - other_info) + 20 /*anonymous_sender*/; -} - -static bool -pad_pkcs7(uint8_t *buf, size_t buf_len, size_t offset) -{ - if (buf_len <= offset) { - // Must have at least 1 byte of padding - return false; - } - - const uint8_t pad_byte = buf_len - offset; - memset(buf + offset, pad_byte, pad_byte); - return true; -} - -static bool -unpad_pkcs7(uint8_t *buf, size_t buf_len, size_t *offset) -{ - if (!buf || !offset || !buf_len) { - return false; - } - - uint8_t err = 0; - const uint8_t pad_byte = buf[buf_len - 1]; - const uint32_t pad_begin = buf_len - pad_byte; - - // TODO: Still >, <, and <=,== are not constant time (maybe?) - err |= (pad_byte > buf_len); - err |= (pad_byte == 0); - - /* Check if padding is OK */ - for (size_t c = 0; c < buf_len; c++) { - err |= (buf[c] ^ pad_byte) * (pad_begin <= c); - } - - *offset = pad_begin; - return (err == 0); -} +#include "bn.h" // Produces kek of size kek_len which corresponds to length of wrapping key static bool @@ -176,27 +69,13 @@ goto end; } - snprintf(kdf_name, sizeof(kdf_name), "SP800-56A(%s)", pgp_hash_name_botan(hash_alg)); + snprintf(kdf_name, sizeof(kdf_name), "SP800-56A(%s)", rnp::Hash::name_backend(hash_alg)); ret = !botan_kdf( kdf_name, kek, kek_len, s.data(), s_len, NULL, 0, other_info, other_info_size); end: return ret && !botan_pk_op_key_agreement_destroy(op_key_agreement); } -bool -ecdh_set_params(pgp_ec_key_t *key, pgp_curve_t curve_id) -{ - for (size_t i = 0; i < ARRAY_SIZE(ecdh_params); i++) { - if (ecdh_params[i].curve == curve_id) { - key->kdf_hash_alg = ecdh_params[i].hash; - key->key_wrap_alg = ecdh_params[i].wrap_alg; - return true; - } - } - - return false; -} - static bool ecdh_load_public_key(botan_pubkey_t *pubkey, const pgp_ec_key_t *key) { @@ -273,7 +152,7 @@ } rnp_result_t -ecdh_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret) +ecdh_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) { botan_pubkey_t bpkey = NULL; botan_privkey_t bskey = NULL; @@ -285,7 +164,7 @@ } if (!ecdh_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng_handle(rng), 0)) { + botan_pubkey_check_key(bpkey, rng->handle(), 0)) { goto done; } if (!secret) { @@ -294,7 +173,7 @@ } if (!ecdh_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng_handle(rng), 0)) { + botan_privkey_check_key(bskey, rng->handle(), 0)) { goto done; } ret = RNP_SUCCESS; @@ -305,7 +184,7 @@ } rnp_result_t -ecdh_encrypt_pkcs5(rng_t * rng, +ecdh_encrypt_pkcs5(rnp::RNG * rng, pgp_ecdh_encrypted_t * out, const uint8_t *const in, size_t in_len, @@ -323,7 +202,12 @@ if (!key || !out || !in || (in_len > sizeof(m))) { return RNP_ERROR_BAD_PARAMETERS; } - +#if !defined(ENABLE_SM2) + if (key->curve == PGP_CURVE_SM2_P_256) { + RNP_LOG("SM2 curve support is disabled."); + return RNP_ERROR_NOT_IMPLEMENTED; + } +#endif const ec_curve_desc_t *curve_desc = get_curve_desc(key->curve); if (!curve_desc) { RNP_LOG("unsupported curve"); @@ -347,12 +231,12 @@ } if (!strcmp(curve_desc->botan_name, "curve25519")) { - if (botan_privkey_create(&eph_prv_key, "Curve25519", "", rng_handle(rng))) { + if (botan_privkey_create(&eph_prv_key, "Curve25519", "", rng->handle())) { goto end; } } else { if (botan_privkey_create( - &eph_prv_key, "ECDH", curve_desc->botan_name, rng_handle(rng))) { + &eph_prv_key, "ECDH", curve_desc->botan_name, rng->handle())) { goto end; } } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh.h 2022-04-15 07:49:22.000000000 +0000 @@ -45,7 +45,7 @@ size_t mlen; } pgp_ecdh_encrypted_t; -rnp_result_t ecdh_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret); +rnp_result_t ecdh_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); /* * @brief Sets hash algorithm and key wrapping algo @@ -62,7 +62,7 @@ * Encrypts session key with a KEK agreed during ECDH as specified in * RFC 4880 bis 01, 13.5 * - * @param rng initialized rng_t object + * @param rng initialized rnp::RNG object * @param session_key key to be encrypted * @param session_key_len length of the key buffer * @param wrapped_key [out] resulting key wrapped in by some AES @@ -81,7 +81,7 @@ * @return RNP_ERROR_SHORT_BUFFER `wrapped_key_len' to small to store result * @return RNP_ERROR_GENERIC implementation error */ -rnp_result_t ecdh_encrypt_pkcs5(rng_t * rng, +rnp_result_t ecdh_encrypt_pkcs5(rnp::RNG * rng, pgp_ecdh_encrypted_t * out, const uint8_t *const in, size_t in_len, diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "ecdh.h" +#include "ecdh_utils.h" +#include "ec_ossl.h" +#include "hash.h" +#include "symmetric.h" +#include "types.h" +#include "utils.h" +#include "logging.h" +#include "mem.h" +#include +#include + +static const struct ecdh_wrap_alg_map_t { + pgp_symm_alg_t alg; + const char * name; +} ecdh_wrap_alg_map[] = {{PGP_SA_AES_128, "aes128-wrap"}, + {PGP_SA_AES_192, "aes192-wrap"}, + {PGP_SA_AES_256, "aes256-wrap"}}; + +rnp_result_t +ecdh_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +{ + return ec_validate_key(*key, secret); +} + +static rnp_result_t +ecdh_derive_kek(uint8_t * x, + size_t xlen, + const pgp_ec_key_t & key, + const pgp_fingerprint_t &fingerprint, + uint8_t * kek, + const size_t kek_len) +{ + const ec_curve_desc_t *curve_desc = get_curve_desc(key.curve); + if (!curve_desc) { + RNP_LOG("unsupported curve"); + return RNP_ERROR_NOT_SUPPORTED; + } + + // Serialize other info, see 13.5 of RFC 4880 bis + uint8_t other_info[MAX_SP800_56A_OTHER_INFO]; + const size_t hash_len = rnp::Hash::size(key.kdf_hash_alg); + if (!hash_len) { + // must not assert here as kdf/hash algs are not checked during key parsing + RNP_LOG("Unsupported key wrap hash algorithm."); + return RNP_ERROR_NOT_SUPPORTED; + } + size_t other_len = kdf_other_info_serialize( + other_info, curve_desc, fingerprint, key.kdf_hash_alg, key.key_wrap_alg); + // Self-check + assert(other_len == curve_desc->OIDhex_len + 46); + // Derive KEK, using the KDF from SP800-56A + rnp::secure_array dgst; + assert(hash_len <= PGP_MAX_HASH_SIZE); + size_t reps = (kek_len + hash_len - 1) / hash_len; + // As we use AES & SHA2 we should not get more then 2 iterations + if (reps > 2) { + RNP_LOG("Invalid key wrap/hash alg combination."); + return RNP_ERROR_NOT_SUPPORTED; + } + size_t have = 0; + try { + for (size_t i = 1; i <= reps; i++) { + rnp::Hash hash(key.kdf_hash_alg); + hash.add(i); + hash.add(x, xlen); + hash.add(other_info, other_len); + hash.finish(dgst.data()); + size_t bytes = std::min(hash_len, kek_len - have); + memcpy(kek + have, dgst.data(), bytes); + have += bytes; + } + return RNP_SUCCESS; + } catch (const std::exception &e) { + RNP_LOG("Failed to derive kek: %s", e.what()); + return RNP_ERROR_GENERIC; + } +} + +static rnp_result_t +ecdh_rfc3394_wrap_ctx(EVP_CIPHER_CTX **ctx, + pgp_symm_alg_t wrap_alg, + const uint8_t * key, + bool decrypt) +{ + /* get OpenSSL EVP cipher for key wrap */ + const char *cipher_name = NULL; + ARRAY_LOOKUP_BY_ID(ecdh_wrap_alg_map, alg, name, wrap_alg, cipher_name); + if (!cipher_name) { + RNP_LOG("Unsupported key wrap algorithm: %d", (int) wrap_alg); + return RNP_ERROR_NOT_SUPPORTED; + } + const EVP_CIPHER *cipher = EVP_get_cipherbyname(cipher_name); + if (!cipher) { + RNP_LOG("Cipher %s is not supported by OpenSSL.", cipher_name); + return RNP_ERROR_NOT_SUPPORTED; + } + *ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + RNP_LOG("Context allocation failed : %lu", ERR_peek_last_error()); + return RNP_ERROR_OUT_OF_MEMORY; + } + EVP_CIPHER_CTX_set_flags(*ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + int res = decrypt ? EVP_DecryptInit_ex(*ctx, cipher, NULL, key, NULL) : + EVP_EncryptInit_ex(*ctx, cipher, NULL, key, NULL); + if (res <= 0) { + RNP_LOG("Failed to initialize cipher : %lu", ERR_peek_last_error()); + EVP_CIPHER_CTX_free(*ctx); + *ctx = NULL; + return RNP_ERROR_GENERIC; + } + return RNP_SUCCESS; +} + +static rnp_result_t +ecdh_rfc3394_wrap(uint8_t * out, + size_t * out_len, + const uint8_t *const in, + size_t in_len, + const uint8_t * key, + pgp_symm_alg_t wrap_alg) +{ + EVP_CIPHER_CTX *ctx = NULL; + rnp_result_t ret = ecdh_rfc3394_wrap_ctx(&ctx, wrap_alg, key, false); + if (ret) { + RNP_LOG("Wrap context initialization failed."); + return ret; + } + int intlen = *out_len; + /* encrypts in one pass, no final is needed */ + int res = EVP_EncryptUpdate(ctx, out, &intlen, in, in_len); + if (res <= 0) { + RNP_LOG("Failed to encrypt data : %lu", ERR_peek_last_error()); + } else { + *out_len = intlen; + } + EVP_CIPHER_CTX_free(ctx); + return res > 0 ? RNP_SUCCESS : RNP_ERROR_GENERIC; +} + +static rnp_result_t +ecdh_rfc3394_unwrap(uint8_t * out, + size_t * out_len, + const uint8_t *const in, + size_t in_len, + const uint8_t * key, + pgp_symm_alg_t wrap_alg) +{ + if ((in_len < 16) || (in_len % 8)) { + RNP_LOG("Invalid wrapped key size."); + return RNP_ERROR_GENERIC; + } + EVP_CIPHER_CTX *ctx = NULL; + rnp_result_t ret = ecdh_rfc3394_wrap_ctx(&ctx, wrap_alg, key, true); + if (ret) { + RNP_LOG("Unwrap context initialization failed."); + return ret; + } + int intlen = *out_len; + /* decrypts in one pass, no final is needed */ + int res = EVP_DecryptUpdate(ctx, out, &intlen, in, in_len); + if (res <= 0) { + RNP_LOG("Failed to decrypt data : %lu", ERR_peek_last_error()); + } else { + *out_len = intlen; + } + EVP_CIPHER_CTX_free(ctx); + return res > 0 ? RNP_SUCCESS : RNP_ERROR_GENERIC; +} + +static bool +ecdh_derive_secret(EVP_PKEY *sec, EVP_PKEY *peer, uint8_t *x, size_t *xlen) +{ + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(sec, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + return false; + } + bool res = false; + if (EVP_PKEY_derive_init(ctx) <= 0) { + RNP_LOG("Key derivation init failed: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_derive_set_peer(ctx, peer) <= 0) { + RNP_LOG("Peer setting failed: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_derive(ctx, x, xlen) <= 0) { + RNP_LOG("Failed to obtain shared secret size: %lu", ERR_peek_last_error()); + goto done; + } + res = true; +done: + EVP_PKEY_CTX_free(ctx); + return res; +} + +static size_t +ecdh_kek_len(pgp_symm_alg_t wrap_alg) +{ + switch (wrap_alg) { + case PGP_SA_AES_128: + case PGP_SA_AES_192: + case PGP_SA_AES_256: + return pgp_key_size(wrap_alg); + default: + return 0; + } +} + +rnp_result_t +ecdh_encrypt_pkcs5(rnp::RNG * rng, + pgp_ecdh_encrypted_t * out, + const uint8_t *const in, + size_t in_len, + const pgp_ec_key_t * key, + const pgp_fingerprint_t &fingerprint) +{ + if (!key || !out || !in || (in_len > MAX_SESSION_KEY_SIZE)) { + return RNP_ERROR_BAD_PARAMETERS; + } +#if !defined(ENABLE_SM2) + if (key->curve == PGP_CURVE_SM2_P_256) { + RNP_LOG("SM2 curve support is disabled."); + return RNP_ERROR_NOT_IMPLEMENTED; + } +#endif + /* check whether we have valid wrap_alg before doing heavy operations */ + size_t keklen = ecdh_kek_len(key->key_wrap_alg); + if (!keklen) { + RNP_LOG("Unsupported key wrap algorithm: %d", (int) key->key_wrap_alg); + return RNP_ERROR_NOT_SUPPORTED; + } + /* load our public key */ + EVP_PKEY *pkey = ec_load_key(key->p, NULL, key->curve); + if (!pkey) { + RNP_LOG("Failed to load public key."); + return RNP_ERROR_BAD_PARAMETERS; + } + rnp::secure_array sec; + rnp::secure_array kek; + rnp::secure_array mpad; + + size_t seclen = sec.size(); + rnp_result_t ret = RNP_ERROR_GENERIC; + /* generate ephemeral key */ + EVP_PKEY *ephkey = ec_generate_pkey(PGP_PKA_ECDH, key->curve); + if (!ephkey) { + RNP_LOG("Failed to generate ephemeral key."); + ret = RNP_ERROR_KEY_GENERATION; + goto done; + } + /* do ECDH derivation */ + if (!ecdh_derive_secret(ephkey, pkey, sec.data(), &seclen)) { + RNP_LOG("ECDH derivation failed."); + goto done; + } + /* here we got x value in sec, deriving kek */ + ret = ecdh_derive_kek(sec.data(), seclen, *key, fingerprint, kek.data(), keklen); + if (ret) { + RNP_LOG("Failed to derive KEK."); + goto done; + } + /* add PKCS#7 padding */ + size_t m_padded_len; + m_padded_len = ((in_len / 8) + 1) * 8; + memcpy(mpad.data(), in, in_len); + if (!pad_pkcs7(mpad.data(), m_padded_len, in_len)) { + RNP_LOG("Failed to add PKCS #7 padding."); + goto done; + } + /* do RFC 3394 AES key wrap */ + static_assert(sizeof(out->m) == ECDH_WRAPPED_KEY_SIZE, "Wrong ECDH wrapped key size."); + out->mlen = ECDH_WRAPPED_KEY_SIZE; + ret = ecdh_rfc3394_wrap( + out->m, &out->mlen, mpad.data(), m_padded_len, kek.data(), key->key_wrap_alg); + if (ret) { + RNP_LOG("Failed to wrap key."); + goto done; + } + /* write ephemeral public key */ + if (!ec_write_pubkey(ephkey, out->p, key->curve)) { + RNP_LOG("Failed to write ec key."); + goto done; + } + ret = RNP_SUCCESS; +done: + EVP_PKEY_free(ephkey); + EVP_PKEY_free(pkey); + return ret; +} + +rnp_result_t +ecdh_decrypt_pkcs5(uint8_t * out, + size_t * out_len, + const pgp_ecdh_encrypted_t *in, + const pgp_ec_key_t * key, + const pgp_fingerprint_t & fingerprint) +{ + if (!out || !out_len || !in || !key || !mpi_bytes(&key->x)) { + return RNP_ERROR_BAD_PARAMETERS; + } + + /* check whether we have valid wrap_alg before doing heavy operations */ + size_t keklen = ecdh_kek_len(key->key_wrap_alg); + if (!keklen) { + RNP_LOG("Unsupported key wrap algorithm: %d", (int) key->key_wrap_alg); + return RNP_ERROR_NOT_SUPPORTED; + } + /* load ephemeral public key */ + EVP_PKEY *ephkey = ec_load_key(in->p, NULL, key->curve); + if (!ephkey) { + RNP_LOG("Failed to load ephemeral public key."); + return RNP_ERROR_BAD_PARAMETERS; + } + /* load our secret key */ + rnp::secure_array sec; + rnp::secure_array kek; + rnp::secure_array mpad; + + size_t seclen = sec.size(); + size_t mpadlen = mpad.size(); + rnp_result_t ret = RNP_ERROR_GENERIC; + EVP_PKEY * pkey = ec_load_key(key->p, &key->x, key->curve); + if (!pkey) { + RNP_LOG("Failed to load secret key."); + ret = RNP_ERROR_BAD_PARAMETERS; + goto done; + } + /* do ECDH derivation */ + if (!ecdh_derive_secret(pkey, ephkey, sec.data(), &seclen)) { + RNP_LOG("ECDH derivation failed."); + goto done; + } + /* here we got x value in sec, deriving kek */ + ret = ecdh_derive_kek(sec.data(), seclen, *key, fingerprint, kek.data(), keklen); + if (ret) { + RNP_LOG("Failed to derive KEK."); + goto done; + } + /* do RFC 3394 AES key unwrap */ + ret = ecdh_rfc3394_unwrap( + mpad.data(), &mpadlen, in->m, in->mlen, kek.data(), key->key_wrap_alg); + if (ret) { + RNP_LOG("Failed to unwrap key."); + goto done; + } + /* remove PKCS#7 padding */ + if (!unpad_pkcs7(mpad.data(), mpadlen, &mpadlen)) { + RNP_LOG("Failed to unpad key."); + goto done; + } + assert(mpadlen <= *out_len); + *out_len = mpadlen; + memcpy(out, mpad.data(), mpadlen); + ret = RNP_SUCCESS; +done: + EVP_PKEY_free(ephkey); + EVP_PKEY_free(pkey); + return ret; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh_utils.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh_utils.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh_utils.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh_utils.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ecdh_utils.h" +#include "types.h" +#include "utils.h" +#include + +/* Used by ECDH keys. Specifies which hash and wrapping algorithm + * to be used (see point 15. of RFC 4880). + * + * Note: sync with ec_curves. + */ +static const struct ecdh_params_t { + pgp_curve_t curve; /* Curve ID */ + pgp_hash_alg_t hash; /* Hash used by kdf */ + pgp_symm_alg_t wrap_alg; /* Symmetric algorithm used to wrap KEK*/ +} ecdh_params[] = { + {.curve = PGP_CURVE_NIST_P_256, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, + {.curve = PGP_CURVE_NIST_P_384, .hash = PGP_HASH_SHA384, .wrap_alg = PGP_SA_AES_192}, + {.curve = PGP_CURVE_NIST_P_521, .hash = PGP_HASH_SHA512, .wrap_alg = PGP_SA_AES_256}, + {.curve = PGP_CURVE_BP256, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, + {.curve = PGP_CURVE_BP384, .hash = PGP_HASH_SHA384, .wrap_alg = PGP_SA_AES_192}, + {.curve = PGP_CURVE_BP512, .hash = PGP_HASH_SHA512, .wrap_alg = PGP_SA_AES_256}, + {.curve = PGP_CURVE_25519, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, + {.curve = PGP_CURVE_P256K1, .hash = PGP_HASH_SHA256, .wrap_alg = PGP_SA_AES_128}, +}; + +// "Anonymous Sender " in hex +static const unsigned char ANONYMOUS_SENDER[] = {0x41, 0x6E, 0x6F, 0x6E, 0x79, 0x6D, 0x6F, + 0x75, 0x73, 0x20, 0x53, 0x65, 0x6E, 0x64, + 0x65, 0x72, 0x20, 0x20, 0x20, 0x20}; + +// returns size of data written to other_info +size_t +kdf_other_info_serialize(uint8_t other_info[MAX_SP800_56A_OTHER_INFO], + const ec_curve_desc_t * ec_curve, + const pgp_fingerprint_t &fingerprint, + const pgp_hash_alg_t kdf_hash, + const pgp_symm_alg_t wrap_alg) +{ + assert(fingerprint.length >= 20); + uint8_t *buf_ptr = &other_info[0]; + + /* KDF-OtherInfo: AlgorithmID + * Current implementation will always use SHA-512 and AES-256 for KEK wrapping + */ + *(buf_ptr++) = ec_curve->OIDhex_len; + memcpy(buf_ptr, ec_curve->OIDhex, ec_curve->OIDhex_len); + buf_ptr += ec_curve->OIDhex_len; + *(buf_ptr++) = PGP_PKA_ECDH; + // size of following 3 params (each 1 byte) + *(buf_ptr++) = 0x03; + // Value reserved for future use + *(buf_ptr++) = 0x01; + // Hash used with KDF + *(buf_ptr++) = kdf_hash; + // Algorithm ID used for key wrapping + *(buf_ptr++) = wrap_alg; + + /* KDF-OtherInfo: PartyUInfo + * 20 bytes representing "Anonymous Sender " + */ + memcpy(buf_ptr, ANONYMOUS_SENDER, sizeof(ANONYMOUS_SENDER)); + buf_ptr += sizeof(ANONYMOUS_SENDER); + + // keep 20, as per spec + memcpy(buf_ptr, fingerprint.fingerprint, 20); + return (buf_ptr - other_info) + 20 /*anonymous_sender*/; +} + +bool +pad_pkcs7(uint8_t *buf, size_t buf_len, size_t offset) +{ + if (buf_len <= offset) { + // Must have at least 1 byte of padding + return false; + } + + const uint8_t pad_byte = buf_len - offset; + memset(buf + offset, pad_byte, pad_byte); + return true; +} + +bool +unpad_pkcs7(uint8_t *buf, size_t buf_len, size_t *offset) +{ + if (!buf || !offset || !buf_len) { + return false; + } + + uint8_t err = 0; + const uint8_t pad_byte = buf[buf_len - 1]; + const uint32_t pad_begin = buf_len - pad_byte; + + // TODO: Still >, <, and <=,== are not constant time (maybe?) + err |= (pad_byte > buf_len); + err |= (pad_byte == 0); + + /* Check if padding is OK */ + for (size_t c = 0; c < buf_len; c++) { + err |= (buf[c] ^ pad_byte) * (pad_begin <= c); + } + + *offset = pad_begin; + return (err == 0); +} + +bool +ecdh_set_params(pgp_ec_key_t *key, pgp_curve_t curve_id) +{ + for (size_t i = 0; i < ARRAY_SIZE(ecdh_params); i++) { + if (ecdh_params[i].curve == curve_id) { + key->kdf_hash_alg = ecdh_params[i].hash; + key->key_wrap_alg = ecdh_params[i].wrap_alg; + return true; + } + } + + return false; +} + +bool +x25519_tweak_bits(pgp_ec_key_t &key) +{ + if (key.x.len != 32) { + return false; + } + /* MPI is big-endian, while raw x25519 key is little-endian */ + key.x.mpi[31] &= 248; // zero 3 low bits + key.x.mpi[0] &= 127; // zero high bit + key.x.mpi[0] |= 64; // set high - 1 bit + return true; +} + +bool +x25519_bits_tweaked(const pgp_ec_key_t &key) +{ + if (key.x.len != 32) { + return false; + } + return !(key.x.mpi[31] & 7) && (key.x.mpi[0] < 128) && (key.x.mpi[0] >= 64); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh_utils.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh_utils.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdh_utils.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdh_utils.h 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECDH_UTILS_H_ +#define ECDH_UTILS_H_ + +#include "ecdh.h" + +#define MAX_SP800_56A_OTHER_INFO 56 +// Keys up to 312 bits (+1 bytes of PKCS5 padding) +#define MAX_SESSION_KEY_SIZE 40 +#define MAX_AES_KEY_SIZE 32 + +size_t kdf_other_info_serialize(uint8_t other_info[MAX_SP800_56A_OTHER_INFO], + const ec_curve_desc_t * ec_curve, + const pgp_fingerprint_t &fingerprint, + const pgp_hash_alg_t kdf_hash, + const pgp_symm_alg_t wrap_alg); + +bool pad_pkcs7(uint8_t *buf, size_t buf_len, size_t offset); + +bool unpad_pkcs7(uint8_t *buf, size_t buf_len, size_t *offset); + +#endif // ECDH_UTILS_H_ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdsa.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdsa.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdsa.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdsa.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -28,6 +28,7 @@ #include "utils.h" #include #include +#include "bn.h" static bool ecdsa_load_public_key(botan_pubkey_t *pubkey, const pgp_ec_key_t *keydata) @@ -44,7 +45,8 @@ const size_t curve_order = BITS_TO_BYTES(curve->bitlen); if (!mpi_bytes(&keydata->p) || (keydata->p.mpi[0] != 0x04)) { - RNP_LOG("Failed to load public key"); + RNP_LOG( + "Failed to load public key: %zu, %02x", mpi_bytes(&keydata->p), keydata->p.mpi[0]); return false; } @@ -84,14 +86,14 @@ } rnp_result_t -ecdsa_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret) +ecdsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) { botan_pubkey_t bpkey = NULL; botan_privkey_t bskey = NULL; rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; if (!ecdsa_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng_handle(rng), 0)) { + botan_pubkey_check_key(bpkey, rng->handle(), 0)) { goto done; } if (!secret) { @@ -100,7 +102,7 @@ } if (!ecdsa_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng_handle(rng), 0)) { + botan_privkey_check_key(bskey, rng->handle(), 0)) { goto done; } ret = RNP_SUCCESS; @@ -142,7 +144,7 @@ } rnp_result_t -ecdsa_sign(rng_t * rng, +ecdsa_sign(rnp::RNG * rng, pgp_ec_signature_t *sig, pgp_hash_alg_t hash_alg, const uint8_t * hash, @@ -175,7 +177,7 @@ goto end; } - if (botan_pk_op_sign_finish(signer, rng_handle(rng), out_buf, &sig_len)) { + if (botan_pk_op_sign_finish(signer, rng->handle(), out_buf, &sig_len)) { RNP_LOG("Signing failed"); goto end; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdsa.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdsa.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdsa.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdsa.h 2022-04-15 07:49:22.000000000 +0000 @@ -29,9 +29,9 @@ #include "crypto/ec.h" -rnp_result_t ecdsa_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret); +rnp_result_t ecdsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); -rnp_result_t ecdsa_sign(rng_t * rng, +rnp_result_t ecdsa_sign(rnp::RNG * rng, pgp_ec_signature_t *sig, pgp_hash_alg_t hash_alg, const uint8_t * hash, diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdsa_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdsa_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ecdsa_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ecdsa_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ecdsa.h" +#include "utils.h" +#include +#include "bn.h" +#include "ec_ossl.h" +#include +#include +#include + +static bool +ecdsa_decode_sig(const uint8_t *data, size_t len, pgp_ec_signature_t &sig) +{ + ECDSA_SIG *esig = d2i_ECDSA_SIG(NULL, &data, len); + if (!esig) { + RNP_LOG("Failed to parse ECDSA sig: %lu", ERR_peek_last_error()); + return false; + } + const BIGNUM *r, *s; + ECDSA_SIG_get0(esig, &r, &s); + bn2mpi(r, &sig.r); + bn2mpi(s, &sig.s); + ECDSA_SIG_free(esig); + return true; +} + +static bool +ecdsa_encode_sig(uint8_t *data, size_t *len, const pgp_ec_signature_t &sig) +{ + bool res = false; + ECDSA_SIG *dsig = ECDSA_SIG_new(); + BIGNUM * r = mpi2bn(&sig.r); + BIGNUM * s = mpi2bn(&sig.s); + if (!dsig || !r || !s) { + RNP_LOG("Allocation failed."); + goto done; + } + ECDSA_SIG_set0(dsig, r, s); + r = NULL; + s = NULL; + int outlen; + outlen = i2d_ECDSA_SIG(dsig, &data); + if (outlen < 0) { + RNP_LOG("Failed to encode signature."); + goto done; + } + *len = outlen; + res = true; +done: + ECDSA_SIG_free(dsig); + BN_free(r); + BN_free(s); + return res; +} + +rnp_result_t +ecdsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +{ + return ec_validate_key(*key, secret); +} + +rnp_result_t +ecdsa_sign(rnp::RNG * rng, + pgp_ec_signature_t *sig, + pgp_hash_alg_t hash_alg, + const uint8_t * hash, + size_t hash_len, + const pgp_ec_key_t *key) +{ + if (mpi_bytes(&key->x) == 0) { + RNP_LOG("private key not set"); + return RNP_ERROR_BAD_PARAMETERS; + } + + /* Load secret key to DSA structure*/ + EVP_PKEY *evpkey = ec_load_key(key->p, &key->x, key->curve); + if (!evpkey) { + RNP_LOG("Failed to load key"); + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_GENERIC; + /* init context and sign */ + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(evpkey, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_sign_init(ctx) <= 0) { + RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); + goto done; + } + sig->s.len = PGP_MPINT_SIZE; + if (EVP_PKEY_sign(ctx, sig->s.mpi, &sig->s.len, hash, hash_len) <= 0) { + RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); + sig->s.len = 0; + goto done; + } + if (!ecdsa_decode_sig(&sig->s.mpi[0], sig->s.len, *sig)) { + RNP_LOG("Failed to parse ECDSA sig: %lu", ERR_peek_last_error()); + goto done; + } + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(evpkey); + return ret; +} + +rnp_result_t +ecdsa_verify(const pgp_ec_signature_t *sig, + pgp_hash_alg_t hash_alg, + const uint8_t * hash, + size_t hash_len, + const pgp_ec_key_t * key) +{ + /* Load secret key to DSA structure*/ + EVP_PKEY *evpkey = ec_load_key(key->p, NULL, key->curve); + if (!evpkey) { + RNP_LOG("Failed to load key"); + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_SIGNATURE_INVALID; + /* init context and sign */ + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(evpkey, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_verify_init(ctx) <= 0) { + RNP_LOG("Failed to initialize verify: %lu", ERR_peek_last_error()); + goto done; + } + pgp_mpi_t sigbuf; + if (!ecdsa_encode_sig(sigbuf.mpi, &sigbuf.len, *sig)) { + goto done; + } + if (EVP_PKEY_verify(ctx, sigbuf.mpi, sigbuf.len, hash, hash_len) > 0) { + ret = RNP_SUCCESS; + } +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(evpkey); + return ret; +} + +pgp_hash_alg_t +ecdsa_get_min_hash(pgp_curve_t curve) +{ + switch (curve) { + case PGP_CURVE_NIST_P_256: + case PGP_CURVE_BP256: + case PGP_CURVE_P256K1: + return PGP_HASH_SHA256; + case PGP_CURVE_NIST_P_384: + case PGP_CURVE_BP384: + return PGP_HASH_SHA384; + case PGP_CURVE_NIST_P_521: + case PGP_CURVE_BP512: + return PGP_HASH_SHA512; + default: + return PGP_HASH_UNKNOWN; + } +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec.h 2022-04-15 07:49:22.000000000 +0000 @@ -30,6 +30,7 @@ #ifndef EC_H_ #define EC_H_ +#include "config.h" #include #include #include "crypto/rng.h" @@ -54,8 +55,15 @@ const size_t bitlen; const uint8_t OIDhex[MAX_CURVE_OID_HEX_LEN]; const size_t OIDhex_len; - const char * botan_name; - const char * pgp_name; +#if defined(CRYPTO_BACKEND_BOTAN) + const char *botan_name; +#endif +#if defined(CRYPTO_BACKEND_OPENSSL) + const char *openssl_name; +#endif + const char *pgp_name; + /* Curve is supported for keygen/sign/encrypt operations */ + bool supported; /* Curve parameters below. Needed for grip calculation */ const char *p; const char *a; @@ -106,10 +114,19 @@ */ const ec_curve_desc_t *get_curve_desc(const pgp_curve_t curve_id); +bool alg_allows_curve(pgp_pubkey_alg_t alg, pgp_curve_t curve); + +/** + * @brief Check whether curve is supported for operations. + * All available curves are supported for reading/parsing key data, however some of them + * may be disabled for use, i.e. for key generation/signing/encryption. + */ +bool curve_supported(pgp_curve_t curve); + /* * @brief Generates EC key in uncompressed format * - * @param rng initialized rng_t context* + * @param rng initialized rnp::RNG context* * @param key key data to be generated * @param alg_id ID of EC algorithm * @param curve underlying ECC curve ID @@ -120,7 +137,7 @@ * @returns RNP_ERROR_OUT_OF_MEMORY memory allocation failed * @returns RNP_ERROR_KEY_GENERATION implementation error */ -rnp_result_t ec_generate(rng_t * rng, +rnp_result_t ec_generate(rnp::RNG * rng, pgp_ec_key_t * key, const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve); @@ -128,11 +145,29 @@ /* * @brief Generates x25519 ECDH key in x25519-specific format * - * @param rng initialized rng_t context* + * @param rng initialized rnp::RNG context* * @param key key data to be generated * * @returns RNP_ERROR_KEY_GENERATION implementation error */ -rnp_result_t x25519_generate(rng_t *rng, pgp_ec_key_t *key); +rnp_result_t x25519_generate(rnp::RNG *rng, pgp_ec_key_t *key); + +/** + * @brief Set least significant/most significant bits of the 25519 secret key as per + * specification. + * + * @param key secret key. + * @return true on success or false otherwise. + */ +bool x25519_tweak_bits(pgp_ec_key_t &key); + +/** + * @brief Check whether least significant/most significant bits of 25519 secret key are + * correctly tweaked. + * + * @param key secret key. + * @return true if bits are set correctly, and false otherwise. + */ +bool x25519_bits_tweaked(const pgp_ec_key_t &key); #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "ec.h" +#include "ec_ossl.h" +#include "bn.h" +#include "types.h" +#include "mem.h" +#include "utils.h" +#include +#include +#include +#include + +static bool +ec_is_raw_key(const pgp_curve_t curve) +{ + return (curve == PGP_CURVE_ED25519) || (curve == PGP_CURVE_25519); +} + +rnp_result_t +x25519_generate(rnp::RNG *rng, pgp_ec_key_t *key) +{ + return ec_generate(rng, key, PGP_PKA_ECDH, PGP_CURVE_25519); +} + +EVP_PKEY * +ec_generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) +{ + if (!alg_allows_curve(alg_id, curve)) { + return NULL; + } + const ec_curve_desc_t *ec_desc = get_curve_desc(curve); + if (!ec_desc) { + return NULL; + } + int nid = OBJ_sn2nid(ec_desc->openssl_name); + if (nid == NID_undef) { + RNP_LOG("Unknown SN: %s", ec_desc->openssl_name); + return NULL; + } + bool raw = ec_is_raw_key(curve); + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(raw ? nid : EVP_PKEY_EC, NULL); + if (!ctx) { + RNP_LOG("Failed to create ctx: %lu", ERR_peek_last_error()); + return NULL; + } + EVP_PKEY *pkey = NULL; + if (EVP_PKEY_keygen_init(ctx) <= 0) { + RNP_LOG("Failed to init keygen: %lu", ERR_peek_last_error()); + goto done; + } + if (!raw && (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) <= 0)) { + RNP_LOG("Failed to set curve nid: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + RNP_LOG("EC keygen failed: %lu", ERR_peek_last_error()); + } +done: + EVP_PKEY_CTX_free(ctx); + return pkey; +} + +static bool +ec_write_raw_seckey(EVP_PKEY *pkey, pgp_ec_key_t *key) +{ + /* EdDSA and X25519 keys are saved in a different way */ + static_assert(sizeof(key->x.mpi) > 32, "mpi is too small."); + key->x.len = sizeof(key->x.mpi); + if (EVP_PKEY_get_raw_private_key(pkey, key->x.mpi, &key->x.len) <= 0) { + RNP_LOG("Failed get raw private key: %lu", ERR_peek_last_error()); + return false; + } + assert(key->x.len == 32); + if (EVP_PKEY_id(pkey) == EVP_PKEY_X25519) { + /* in OpenSSL private key is exported as little-endian, while MPI is big-endian */ + for (size_t i = 0; i < 16; i++) { + std::swap(key->x.mpi[i], key->x.mpi[31 - i]); + } + } + return true; +} + +rnp_result_t +ec_generate(rnp::RNG * rng, + pgp_ec_key_t * key, + const pgp_pubkey_alg_t alg_id, + const pgp_curve_t curve) +{ + EVP_PKEY *pkey = ec_generate_pkey(alg_id, curve); + if (!pkey) { + return RNP_ERROR_BAD_PARAMETERS; + } + rnp_result_t ret = RNP_ERROR_GENERIC; + if (ec_is_raw_key(curve)) { + if (ec_write_pubkey(pkey, key->p, curve) && ec_write_raw_seckey(pkey, key)) { + ret = RNP_SUCCESS; + } + EVP_PKEY_free(pkey); + return ret; + } + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + if (!ec) { + RNP_LOG("Failed to retrieve EC key: %lu", ERR_peek_last_error()); + goto done; + } + if (!ec_write_pubkey(pkey, key->p, curve)) { + RNP_LOG("Failed to write pubkey."); + goto done; + } + const bignum_t *x; + x = EC_KEY_get0_private_key(ec); + if (!x) { + ret = RNP_ERROR_BAD_STATE; + goto done; + } + if (bn2mpi(x, &key->x)) { + ret = RNP_SUCCESS; + } +done: + EVP_PKEY_free(pkey); + return ret; +} + +static EVP_PKEY * +ec_load_raw_key(const pgp_mpi_t &keyp, const pgp_mpi_t *keyx, int nid) +{ + if (!keyx) { + /* as per RFC, EdDSA & 25519 keys must use 0x40 byte for encoding */ + if ((mpi_bytes(&keyp) != 33) || (keyp.mpi[0] != 0x40)) { + RNP_LOG("Invalid 25519 public key."); + return NULL; + } + + EVP_PKEY *evpkey = + EVP_PKEY_new_raw_public_key(nid, NULL, &keyp.mpi[1], mpi_bytes(&keyp) - 1); + if (!evpkey) { + RNP_LOG("Failed to load public key: %lu", ERR_peek_last_error()); + } + return evpkey; + } + + EVP_PKEY *evpkey = NULL; + if (nid == EVP_PKEY_X25519) { + if (keyx->len != 32) { + RNP_LOG("Invalid 25519 secret key"); + return NULL; + } + /* need to reverse byte order since in mpi we have big-endian */ + rnp::secure_array prkey; + for (int i = 0; i < 32; i++) { + prkey[i] = keyx->mpi[31 - i]; + } + evpkey = EVP_PKEY_new_raw_private_key(nid, NULL, prkey.data(), keyx->len); + } else { + if (keyx->len > 32) { + RNP_LOG("Invalid Ed25519 secret key"); + return NULL; + } + /* keyx->len may be smaller then 32 as high byte is random and could become 0 */ + rnp::secure_array prkey{}; + memcpy(prkey.data() + 32 - keyx->len, keyx->mpi, keyx->len); + evpkey = EVP_PKEY_new_raw_private_key(nid, NULL, prkey.data(), 32); + } + if (!evpkey) { + RNP_LOG("Failed to load private key: %lu", ERR_peek_last_error()); + } + return evpkey; +} + +EVP_PKEY * +ec_load_key(const pgp_mpi_t &keyp, const pgp_mpi_t *keyx, pgp_curve_t curve) +{ + const ec_curve_desc_t *curv_desc = get_curve_desc(curve); + if (!curv_desc) { + RNP_LOG("unknown curve"); + return NULL; + } + if (!curve_supported(curve)) { + RNP_LOG("Curve %s is not supported.", curv_desc->pgp_name); + return NULL; + } + int nid = OBJ_sn2nid(curv_desc->openssl_name); + if (nid == NID_undef) { + RNP_LOG("Unknown SN: %s", curv_desc->openssl_name); + return NULL; + } + /* EdDSA and X25519 keys are loaded in a different way */ + if (ec_is_raw_key(curve)) { + return ec_load_raw_key(keyp, keyx, nid); + } + EC_KEY *ec = EC_KEY_new_by_curve_name(nid); + if (!ec) { + RNP_LOG("Failed to create EC key with group %d (%s): %s", + nid, + curv_desc->openssl_name, + ERR_reason_error_string(ERR_peek_last_error())); + return NULL; + } + + bool res = false; + bignum_t *x = NULL; + EVP_PKEY *pkey = NULL; + EC_POINT *p = EC_POINT_new(EC_KEY_get0_group(ec)); + if (!p) { + RNP_LOG("Failed to allocate point: %lu", ERR_peek_last_error()); + goto done; + } + if (EC_POINT_oct2point(EC_KEY_get0_group(ec), p, keyp.mpi, keyp.len, NULL) <= 0) { + RNP_LOG("Failed to decode point: %lu", ERR_peek_last_error()); + goto done; + } + if (EC_KEY_set_public_key(ec, p) <= 0) { + RNP_LOG("Failed to set public key: %lu", ERR_peek_last_error()); + goto done; + } + + pkey = EVP_PKEY_new(); + if (!pkey) { + RNP_LOG("EVP_PKEY allocation failed: %lu", ERR_peek_last_error()); + goto done; + } + if (!keyx) { + res = true; + goto done; + } + + x = mpi2bn(keyx); + if (!x) { + RNP_LOG("allocation failed"); + goto done; + } + if (EC_KEY_set_private_key(ec, x) <= 0) { + RNP_LOG("Failed to set secret key: %lu", ERR_peek_last_error()); + goto done; + } + res = true; +done: + if (res) { + res = EVP_PKEY_set1_EC_KEY(pkey, ec) > 0; + } + EC_POINT_free(p); + BN_free(x); + EC_KEY_free(ec); + if (!res) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return pkey; +} + +rnp_result_t +ec_validate_key(const pgp_ec_key_t &key, bool secret) +{ + if (key.curve == PGP_CURVE_25519) { + /* No key check implementation for x25519 in the OpenSSL yet, so just basic size checks + */ + if ((mpi_bytes(&key.p) != 33) || (key.p.mpi[0] != 0x40)) { + return RNP_ERROR_BAD_PARAMETERS; + } + if (secret && mpi_bytes(&key.x) != 32) { + return RNP_ERROR_BAD_PARAMETERS; + } + return RNP_SUCCESS; + } + EVP_PKEY *evpkey = ec_load_key(key.p, secret ? &key.x : NULL, key.curve); + if (!evpkey) { + return RNP_ERROR_BAD_PARAMETERS; + } + rnp_result_t ret = RNP_ERROR_GENERIC; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(evpkey, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + goto done; + } + int res; + res = secret ? EVP_PKEY_check(ctx) : EVP_PKEY_public_check(ctx); + if (res < 0) { + auto err = ERR_peek_last_error(); + RNP_LOG("EC key check failed: %lu (%s)", err, ERR_reason_error_string(err)); + } + if (res > 0) { + ret = RNP_SUCCESS; + } +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(evpkey); + return ret; +} + +bool +ec_write_pubkey(EVP_PKEY *pkey, pgp_mpi_t &mpi, pgp_curve_t curve) +{ + if (ec_is_raw_key(curve)) { + /* EdDSA and X25519 keys are saved in a different way */ + mpi.len = sizeof(mpi.mpi) - 1; + if (EVP_PKEY_get_raw_public_key(pkey, &mpi.mpi[1], &mpi.len) <= 0) { + RNP_LOG("Failed get raw public key: %lu", ERR_peek_last_error()); + return false; + } + assert(mpi.len == 32); + mpi.mpi[0] = 0x40; + mpi.len++; + return true; + } + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + if (!ec) { + RNP_LOG("Failed to retrieve EC key: %lu", ERR_peek_last_error()); + return false; + } + const EC_POINT *p = EC_KEY_get0_public_key(ec); + if (!p) { + RNP_LOG("Null point: %lu", ERR_peek_last_error()); + return false; + } + /* call below adds leading zeroes if needed */ + mpi.len = EC_POINT_point2oct( + EC_KEY_get0_group(ec), p, POINT_CONVERSION_UNCOMPRESSED, mpi.mpi, sizeof(mpi.mpi), NULL); + if (!mpi.len) { + RNP_LOG("Failed to encode public key: %lu", ERR_peek_last_error()); + } + return mpi.len; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec_ossl.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec_ossl.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/ec_ossl.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/ec_ossl.h 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EC_OSSL_H_ +#define EC_OSSL_H_ + +#include "types.h" +#include "ec.h" +#include + +EVP_PKEY *ec_load_key(const pgp_mpi_t &keyp, const pgp_mpi_t *keyx, pgp_curve_t curve); + +rnp_result_t ec_validate_key(const pgp_ec_key_t &key, bool secret); + +EVP_PKEY *ec_generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve); + +bool ec_write_pubkey(EVP_PKEY *key, pgp_mpi_t &mpi, pgp_curve_t curve); + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/eddsa.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/eddsa.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/eddsa.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/eddsa.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -70,14 +70,14 @@ } rnp_result_t -eddsa_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret) +eddsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) { botan_pubkey_t bpkey = NULL; botan_privkey_t bskey = NULL; rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; if (!eddsa_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng_handle(rng), 0)) { + botan_pubkey_check_key(bpkey, rng->handle(), 0)) { goto done; } @@ -87,7 +87,7 @@ } if (!eddsa_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng_handle(rng), 0)) { + botan_privkey_check_key(bskey, rng->handle(), 0)) { goto done; } ret = RNP_SUCCESS; @@ -98,17 +98,13 @@ } rnp_result_t -eddsa_generate(rng_t *rng, pgp_ec_key_t *key, size_t numbits) +eddsa_generate(rnp::RNG *rng, pgp_ec_key_t *key) { botan_privkey_t eddsa = NULL; rnp_result_t ret = RNP_ERROR_GENERIC; uint8_t key_bits[64]; - if (numbits != 255) { - return RNP_ERROR_BAD_PARAMETERS; - } - - if (botan_privkey_create(&eddsa, "Ed25519", NULL, rng_handle(rng)) != 0) { + if (botan_privkey_create(&eddsa, "Ed25519", NULL, rng->handle()) != 0) { goto end; } @@ -172,7 +168,7 @@ } rnp_result_t -eddsa_sign(rng_t * rng, +eddsa_sign(rnp::RNG * rng, pgp_ec_signature_t *sig, const uint8_t * hash, size_t hash_len, @@ -197,7 +193,7 @@ goto done; } - if (botan_pk_op_sign_finish(sign_op, rng_handle(rng), bn_buf, &sig_size) != 0) { + if (botan_pk_op_sign_finish(sign_op, rng->handle(), bn_buf, &sig_size) != 0) { goto done; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/eddsa.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/eddsa.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/eddsa.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/eddsa.h 2022-04-15 07:49:22.000000000 +0000 @@ -33,19 +33,19 @@ #include "ec.h" -rnp_result_t eddsa_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret); +rnp_result_t eddsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); /* * curve_len must be 255 currently (for Ed25519) * If Ed448 was supported in the future curve_len=448 would also be allowed. */ -rnp_result_t eddsa_generate(rng_t *rng, pgp_ec_key_t *key, size_t numbits); +rnp_result_t eddsa_generate(rnp::RNG *rng, pgp_ec_key_t *key); rnp_result_t eddsa_verify(const pgp_ec_signature_t *sig, const uint8_t * hash, size_t hash_len, const pgp_ec_key_t * key); -rnp_result_t eddsa_sign(rng_t * rng, +rnp_result_t eddsa_sign(rnp::RNG * rng, pgp_ec_signature_t *sig, const uint8_t * hash, size_t hash_len, diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/eddsa_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/eddsa_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/eddsa_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/eddsa_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "eddsa.h" +#include "ec.h" +#include "ec_ossl.h" +#include "utils.h" +#include "bn.h" +#include +#include +#include +#include + +rnp_result_t +eddsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +{ + /* Not implemented in the OpenSSL, so just do basic size checks. */ + if ((mpi_bytes(&key->p) != 33) || (key->p.mpi[0] != 0x40)) { + return RNP_ERROR_BAD_PARAMETERS; + } + if (secret && mpi_bytes(&key->x) > 32) { + return RNP_ERROR_BAD_PARAMETERS; + } + return RNP_SUCCESS; +} + +rnp_result_t +eddsa_generate(rnp::RNG *rng, pgp_ec_key_t *key) +{ + rnp_result_t ret = ec_generate(rng, key, PGP_PKA_EDDSA, PGP_CURVE_ED25519); + if (!ret) { + key->curve = PGP_CURVE_ED25519; + } + return ret; +} + +rnp_result_t +eddsa_verify(const pgp_ec_signature_t *sig, + const uint8_t * hash, + size_t hash_len, + const pgp_ec_key_t * key) +{ + if ((mpi_bytes(&sig->r) > 32) || (mpi_bytes(&sig->s) > 32)) { + RNP_LOG("Invalid EdDSA signature."); + return RNP_ERROR_BAD_PARAMETERS; + } + if ((mpi_bytes(&key->p) != 33) || (key->p.mpi[0] != 0x40)) { + RNP_LOG("Invalid EdDSA public key."); + return RNP_ERROR_BAD_PARAMETERS; + } + + EVP_PKEY *evpkey = ec_load_key(key->p, NULL, PGP_CURVE_ED25519); + if (!evpkey) { + RNP_LOG("Failed to load key"); + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_SIGNATURE_INVALID; + uint8_t sigbuf[64] = {0}; + /* init context and sign */ + EVP_PKEY_CTX *ctx = NULL; + EVP_MD_CTX * md = EVP_MD_CTX_new(); + if (!md) { + RNP_LOG("Failed to allocate MD ctx: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_DigestVerifyInit(md, &ctx, NULL, NULL, evpkey) <= 0) { + RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); + goto done; + } + mpi2mem(&sig->r, &sigbuf[32 - mpi_bytes(&sig->r)]); + mpi2mem(&sig->s, &sigbuf[64 - mpi_bytes(&sig->s)]); + + if (EVP_DigestVerify(md, sigbuf, 64, hash, hash_len) > 0) { + ret = RNP_SUCCESS; + } +done: + /* line below will also free ctx */ + EVP_MD_CTX_free(md); + EVP_PKEY_free(evpkey); + return ret; +} + +rnp_result_t +eddsa_sign(rnp::RNG * rng, + pgp_ec_signature_t *sig, + const uint8_t * hash, + size_t hash_len, + const pgp_ec_key_t *key) +{ + if (!mpi_bytes(&key->x)) { + RNP_LOG("private key not set"); + return RNP_ERROR_BAD_PARAMETERS; + } + EVP_PKEY *evpkey = ec_load_key(key->p, &key->x, PGP_CURVE_ED25519); + if (!evpkey) { + RNP_LOG("Failed to load private key: %lu", ERR_peek_last_error()); + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_GENERIC; + /* init context and sign */ + EVP_PKEY_CTX *ctx = NULL; + EVP_MD_CTX * md = EVP_MD_CTX_new(); + if (!md) { + RNP_LOG("Failed to allocate MD ctx: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_DigestSignInit(md, &ctx, NULL, NULL, evpkey) <= 0) { + RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); + goto done; + } + static_assert((sizeof(sig->r.mpi) == PGP_MPINT_SIZE) && (PGP_MPINT_SIZE >= 64), + "invalid mpi type/size"); + sig->r.len = PGP_MPINT_SIZE; + if (EVP_DigestSign(md, sig->r.mpi, &sig->r.len, hash, hash_len) <= 0) { + RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); + sig->r.len = 0; + goto done; + } + assert(sig->r.len == 64); + sig->r.len = 32; + sig->s.len = 32; + memcpy(sig->s.mpi, &sig->r.mpi[32], 32); + ret = RNP_SUCCESS; +done: + /* line below will also free ctx */ + EVP_MD_CTX_free(md); + EVP_PKEY_free(evpkey); + return ret; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/elgamal.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/elgamal.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/elgamal.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/elgamal.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017 Ribose Inc. + * Copyright (c) 2017-2022 Ribose Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,64 +24,16 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Alistair Crooks (agc@NetBSD.org) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - #include #include #include +#include +#include +#include #include #include "elgamal.h" #include "utils.h" +#include "bn.h" // Max supported key byte size #define ELGAMAL_MAX_P_BYTELEN BITS_TO_BYTES(PGP_MPINT_BITS) @@ -140,37 +92,53 @@ return res; } -rnp_result_t -elgamal_validate_key(rng_t *rng, const pgp_eg_key_t *key, bool secret) +bool +elgamal_validate_key(const pgp_eg_key_t *key, bool secret) { - botan_pubkey_t bpkey = NULL; - botan_privkey_t bskey = NULL; - rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; - // Check if provided public key byte size is not greater than ELGAMAL_MAX_P_BYTELEN. - if (!elgamal_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng_handle(rng), 0)) { - goto done; + if (mpi_bytes(&key->p) > ELGAMAL_MAX_P_BYTELEN) { + return false; } - if (!secret) { - ret = RNP_SUCCESS; - goto done; + /* Use custom validation since we added some custom validation, and Botan has slow test for + * prime for p */ + try { + Botan::BigInt p(key->p.mpi, key->p.len); + Botan::BigInt g(key->g.mpi, key->g.len); + + /* 1 < g < p */ + if ((g.cmp_word(1) != 1) || (g.cmp(p) != -1)) { + return false; + } + /* g ^ (p - 1) = 1 mod p */ + if (Botan::power_mod(g, p - 1, p).cmp_word(1)) { + return false; + } + /* check for small order subgroups */ + Botan::Modular_Reducer reducer(p); + Botan::BigInt v = g; + for (size_t i = 2; i < (1 << 17); i++) { + v = reducer.multiply(v, g); + if (!v.cmp_word(1)) { + RNP_LOG("Small subgroup detected. Order %zu", i); + return false; + } + } + if (!secret) { + return true; + } + /* check that g ^ x = y (mod p) */ + Botan::BigInt y(key->y.mpi, key->y.len); + Botan::BigInt x(key->x.mpi, key->x.len); + return Botan::power_mod(g, x, p) == y; + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; } - - if (!elgamal_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng_handle(rng), 0)) { - goto done; - } - ret = RNP_SUCCESS; -done: - botan_privkey_destroy(bskey); - botan_pubkey_destroy(bpkey); - return ret; } rnp_result_t -elgamal_encrypt_pkcs1(rng_t * rng, +elgamal_encrypt_pkcs1(rnp::RNG * rng, pgp_eg_encrypted_t *out, const uint8_t * in, size_t in_len, @@ -197,7 +165,7 @@ p_len = mpi_bytes(&key->p) * 2; if (botan_pk_op_encrypt_create(&op_ctx, b_key, "PKCS1v15", 0) || - botan_pk_op_encrypt(op_ctx, rng_handle(rng), enc_buf, &p_len, in, in_len)) { + botan_pk_op_encrypt(op_ctx, rng->handle(), enc_buf, &p_len, in, in_len)) { RNP_LOG("Failed to create operation context"); goto end; } @@ -224,7 +192,7 @@ } rnp_result_t -elgamal_decrypt_pkcs1(rng_t * rng, +elgamal_decrypt_pkcs1(rnp::RNG * rng, uint8_t * out, size_t * out_len, const pgp_eg_encrypted_t *in, @@ -278,7 +246,7 @@ } rnp_result_t -elgamal_generate(rng_t *rng, pgp_eg_key_t *key, size_t keybits) +elgamal_generate(rnp::RNG *rng, pgp_eg_key_t *key, size_t keybits) { if ((keybits < 1024) || (keybits > PGP_MPINT_BITS)) { return RNP_ERROR_BAD_PARAMETERS; @@ -290,7 +258,6 @@ bignum_t * g = bn_new(); bignum_t * y = bn_new(); bignum_t * x = bn_new(); - size_t ybytes = 0; if (!p || !g || !y || !x) { ret = RNP_ERROR_OUT_OF_MEMORY; @@ -298,19 +265,17 @@ } start: - if (botan_privkey_create_elgamal(&key_priv, rng_handle(rng), keybits, keybits - 1)) { + if (botan_privkey_create_elgamal(&key_priv, rng->handle(), keybits, keybits - 1)) { RNP_LOG("Wrong parameters"); ret = RNP_ERROR_BAD_PARAMETERS; goto end; } - if (botan_privkey_get_field(BN_HANDLE_PTR(y), key_priv, "y") || - !bn_num_bytes(y, &ybytes)) { + if (botan_privkey_get_field(BN_HANDLE_PTR(y), key_priv, "y")) { RNP_LOG("Failed to obtain public key"); goto end; } - if (ybytes < BITS_TO_BYTES(keybits)) { - RNP_DLOG("Generated ElGamal key has too few bits - retrying"); + if (bn_num_bytes(*y) < BITS_TO_BYTES(keybits)) { botan_privkey_destroy(key_priv); goto start; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/elgamal.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/elgamal.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/elgamal.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/elgamal.h 2022-04-15 07:49:21.000000000 +0000 @@ -1,11 +1,7 @@ -/* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). +/*- + * Copyright (c) 2017-2022 Ribose Inc. * All rights reserved. * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and - * carried further by Ribose Inc (https://www.ribose.com). - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -55,13 +51,13 @@ pgp_mpi_t m; } pgp_eg_encrypted_t; -rnp_result_t elgamal_validate_key(rng_t *rng, const pgp_eg_key_t *key, bool secret); +bool elgamal_validate_key(const pgp_eg_key_t *key, bool secret); /* * Performs ElGamal encryption * Result of an encryption is composed of two parts - g2k and encm * - * @param rng initialized rng_t + * @param rng initialized rnp::RNG * @param out encryption result * @param in plaintext to be encrypted * @param in_len length of the plaintext @@ -74,7 +70,7 @@ * RNP_ERROR_OUT_OF_MEMORY allocation failure * RNP_ERROR_BAD_PARAMETERS wrong input provided */ -rnp_result_t elgamal_encrypt_pkcs1(rng_t * rng, +rnp_result_t elgamal_encrypt_pkcs1(rnp::RNG * rng, pgp_eg_encrypted_t *out, const uint8_t * in, size_t in_len, @@ -83,7 +79,7 @@ /* * Performs ElGamal decryption * - * @param rng initialized rng_t + * @param rng initialized rnp::RNG * @param out decrypted plaintext. Must be capable of storing at least as much bytes as p size * @param out_len number of plaintext bytes written will be put here * @param in encrypted data @@ -97,7 +93,7 @@ * RNP_ERROR_OUT_OF_MEMORY allocation failure * RNP_ERROR_BAD_PARAMETERS wrong input provided */ -rnp_result_t elgamal_decrypt_pkcs1(rng_t * rng, +rnp_result_t elgamal_decrypt_pkcs1(rnp::RNG * rng, uint8_t * out, size_t * out_len, const pgp_eg_encrypted_t *in, @@ -116,5 +112,5 @@ * RNP_ERROR_GENERIC internal error * RNP_SUCCESS key generated and copied to `seckey' */ -rnp_result_t elgamal_generate(rng_t *rng, pgp_eg_key_t *key, size_t keybits); +rnp_result_t elgamal_generate(rnp::RNG *rng, pgp_eg_key_t *key, size_t keybits); #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/elgamal_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/elgamal_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/elgamal_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/elgamal_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "elgamal.h" +#include "dl_ossl.h" +#include "utils.h" +#include "bn.h" +#include "mem.h" +#include +#include +#include +#include +#include + +// Max supported key byte size +#define ELGAMAL_MAX_P_BYTELEN BITS_TO_BYTES(PGP_MPINT_BITS) + +bool +elgamal_validate_key(const pgp_eg_key_t *key, bool secret) +{ + BN_CTX *ctx = BN_CTX_new(); + if (!ctx) { + RNP_LOG("Allocation failed."); + return false; + } + BN_CTX_start(ctx); + bool res = false; + bignum_t * p = mpi2bn(&key->p); + bignum_t * g = mpi2bn(&key->g); + bignum_t * p1 = BN_CTX_get(ctx); + bignum_t * r = BN_CTX_get(ctx); + bignum_t * y = NULL; + bignum_t * x = NULL; + BN_RECP_CTX *rctx = NULL; + + if (!p || !g || !p1 || !r) { + goto done; + } + + /* 1 < g < p */ + if ((BN_cmp(g, BN_value_one()) != 1) || (BN_cmp(g, p) != -1)) { + RNP_LOG("Invalid g value."); + goto done; + } + /* g ^ (p - 1) = 1 mod p */ + if (!BN_copy(p1, p) || !BN_sub_word(p1, 1) || !BN_mod_exp(r, g, p1, p, ctx)) { + RNP_LOG("g exp failed."); + goto done; + } + if (BN_cmp(r, BN_value_one()) != 0) { + RNP_LOG("Wrong g exp value."); + goto done; + } + /* check for small order subgroups */ + rctx = BN_RECP_CTX_new(); + if (!rctx || !BN_RECP_CTX_set(rctx, p, ctx) || !BN_copy(r, g)) { + RNP_LOG("Failed to init RECP context."); + goto done; + } + for (size_t i = 2; i < (1 << 17); i++) { + if (!BN_mod_mul_reciprocal(r, r, g, rctx, ctx)) { + RNP_LOG("Multiplication failed."); + goto done; + } + if (BN_cmp(r, BN_value_one()) == 0) { + RNP_LOG("Small subgroup detected. Order %zu", i); + goto done; + } + } + if (!secret) { + res = true; + goto done; + } + /* check that g ^ x = y (mod p) */ + x = mpi2bn(&key->x); + y = mpi2bn(&key->y); + if (!x || !y) { + goto done; + } + res = BN_mod_exp(r, g, x, p, ctx) && !BN_cmp(r, y); +done: + BN_CTX_free(ctx); + BN_RECP_CTX_free(rctx); + bn_free(p); + bn_free(g); + bn_free(y); + bn_free(x); + return res; +} + +static bool +pkcs1v15_pad(uint8_t *out, size_t out_len, const uint8_t *in, size_t in_len) +{ + assert(out && in); + if (out_len < in_len + 11) { + return false; + } + out[0] = 0x00; + out[1] = 0x02; + size_t rnd = out_len - in_len - 3; + out[2 + rnd] = 0x00; + if (RAND_bytes(&out[2], rnd) != 1) { + return false; + } + for (size_t i = 2; i < 2 + rnd; i++) { + /* we need non-zero bytes */ + size_t cntr = 16; + while (!out[i] && (cntr--) && (RAND_bytes(&out[i], 1) == 1)) { + } + if (!out[i]) { + RNP_LOG("Something is wrong with RNG."); + return false; + } + } + memcpy(out + rnd + 3, in, in_len); + return true; +} + +static bool +pkcs1v15_unpad(size_t *padlen, const uint8_t *in, size_t in_len, bool skip0) +{ + if (in_len <= (size_t)(11 - skip0)) { + return false; + } + if (!skip0 && in[0]) { + return false; + } + if (in[1 - skip0] != 0x02) { + return false; + } + size_t pad = 2 - skip0; + while ((pad < in_len) && in[pad]) { + pad++; + } + if (pad >= in_len) { + return false; + } + *padlen = pad + 1; + return true; +} + +rnp_result_t +elgamal_encrypt_pkcs1(rnp::RNG * rng, + pgp_eg_encrypted_t *out, + const uint8_t * in, + size_t in_len, + const pgp_eg_key_t *key) +{ + pgp_mpi_t mm = {}; + mm.len = key->p.len; + if (!pkcs1v15_pad(mm.mpi, mm.len, in, in_len)) { + RNP_LOG("Failed to add PKCS1 v1.5 padding."); + return RNP_ERROR_BAD_PARAMETERS; + } + rnp_result_t ret = RNP_ERROR_GENERIC; + BN_CTX * ctx = BN_CTX_new(); + if (!ctx) { + RNP_LOG("Allocation failed."); + return RNP_ERROR_OUT_OF_MEMORY; + } + BN_CTX_start(ctx); + BN_MONT_CTX *mctx = BN_MONT_CTX_new(); + bignum_t * m = mpi2bn(&mm); + bignum_t * p = mpi2bn(&key->p); + bignum_t * g = mpi2bn(&key->g); + bignum_t * y = mpi2bn(&key->y); + bignum_t * c1 = BN_CTX_get(ctx); + bignum_t * c2 = BN_CTX_get(ctx); + bignum_t * k = BN_secure_new(); + if (!mctx || !m || !p || !g || !y || !c1 || !c2 || !k) { + RNP_LOG("Allocation failed."); + ret = RNP_ERROR_OUT_OF_MEMORY; + goto done; + } + /* initialize Montgomery context */ + if (BN_MONT_CTX_set(mctx, p, ctx) < 1) { + RNP_LOG("Failed to setup Montgomery context."); + goto done; + } + int res; + /* must not fail */ + res = BN_rshift1(c1, p); + assert(res == 1); + if (res < 1) { + RNP_LOG("BN_rshift1 failed."); + goto done; + } + /* generate k */ + if (BN_rand_range(k, c1) < 1) { + RNP_LOG("Failed to generate k."); + goto done; + } + /* calculate c1 = g ^ k (mod p) */ + if (BN_mod_exp_mont_consttime(c1, g, k, p, ctx, mctx) < 1) { + RNP_LOG("Exponentiation 1 failed"); + goto done; + } + /* calculate c2 = m * y ^ k (mod p)*/ + if (BN_mod_exp_mont_consttime(c2, y, k, p, ctx, mctx) < 1) { + RNP_LOG("Exponentiation 2 failed"); + goto done; + } + if (BN_mod_mul(c2, c2, m, p, ctx) < 1) { + RNP_LOG("Multiplication failed"); + goto done; + } + res = bn2mpi(c1, &out->g) && bn2mpi(c2, &out->m); + assert(res == 1); + ret = RNP_SUCCESS; +done: + BN_MONT_CTX_free(mctx); + BN_CTX_free(ctx); + bn_free(m); + bn_free(p); + bn_free(g); + bn_free(y); + bn_free(k); + return ret; +} + +rnp_result_t +elgamal_decrypt_pkcs1(rnp::RNG * rng, + uint8_t * out, + size_t * out_len, + const pgp_eg_encrypted_t *in, + const pgp_eg_key_t * key) +{ + if (!mpi_bytes(&key->x)) { + RNP_LOG("Secret key not set."); + return RNP_ERROR_BAD_PARAMETERS; + } + BN_CTX *ctx = BN_CTX_new(); + if (!ctx) { + RNP_LOG("Allocation failed."); + return RNP_ERROR_OUT_OF_MEMORY; + } + pgp_mpi_t mm = {}; + size_t padlen = 0; + rnp_result_t ret = RNP_ERROR_GENERIC; + BN_CTX_start(ctx); + BN_MONT_CTX *mctx = BN_MONT_CTX_new(); + bignum_t * p = mpi2bn(&key->p); + bignum_t * g = mpi2bn(&key->g); + bignum_t * x = mpi2bn(&key->x); + bignum_t * c1 = mpi2bn(&in->g); + bignum_t * c2 = mpi2bn(&in->m); + bignum_t * s = BN_CTX_get(ctx); + bignum_t * m = BN_secure_new(); + if (!mctx || !p || !g || !x || !c1 || !c2 || !m) { + RNP_LOG("Allocation failed."); + ret = RNP_ERROR_OUT_OF_MEMORY; + goto done; + } + /* initialize Montgomery context */ + if (BN_MONT_CTX_set(mctx, p, ctx) < 1) { + RNP_LOG("Failed to setup Montgomery context."); + goto done; + } + /* calculate s = c1 ^ x (mod p) */ + if (BN_mod_exp_mont_consttime(s, c1, x, p, ctx, mctx) < 1) { + RNP_LOG("Exponentiation 1 failed"); + goto done; + } + /* calculate s^-1 (mod p) */ + BN_set_flags(s, BN_FLG_CONSTTIME); + if (!BN_mod_inverse(s, s, p, ctx)) { + RNP_LOG("Failed to calculate inverse."); + goto done; + } + /* calculate m = c2 * s ^ -1 (mod p)*/ + if (BN_mod_mul(m, c2, s, p, ctx) < 1) { + RNP_LOG("Multiplication failed"); + goto done; + } + bool res; + res = bn2mpi(m, &mm); + assert(res); + if (!res) { + RNP_LOG("bn2mpi failed."); + goto done; + } + /* unpad, handling skipped leftmost 0 case */ + if (!pkcs1v15_unpad(&padlen, mm.mpi, mm.len, mm.len == key->p.len - 1)) { + RNP_LOG("Unpad failed."); + goto done; + } + *out_len = mm.len - padlen; + memcpy(out, &mm.mpi[padlen], *out_len); + ret = RNP_SUCCESS; +done: + secure_clear(mm.mpi, PGP_MPINT_SIZE); + BN_MONT_CTX_free(mctx); + BN_CTX_free(ctx); + bn_free(p); + bn_free(g); + bn_free(x); + bn_free(c1); + bn_free(c2); + bn_free(m); + return ret; +} + +rnp_result_t +elgamal_generate(rnp::RNG *rng, pgp_eg_key_t *key, size_t keybits) +{ + if ((keybits < 1024) || (keybits > PGP_MPINT_BITS)) { + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_GENERIC; + DH * dh = NULL; + EVP_PKEY * pkey = NULL; + EVP_PKEY * parmkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + + /* Generate DH params, which usable for ElGamal as well */ + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); + if (!ctx) { + RNP_LOG("Failed to create ctx: %lu", ERR_peek_last_error()); + return ret; + } + if (EVP_PKEY_paramgen_init(ctx) <= 0) { + RNP_LOG("Failed to init keygen: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, keybits) <= 0) { + RNP_LOG("Failed to set key bits: %lu", ERR_peek_last_error()); + goto done; + } + /* OpenSSL correctly handles case with g = 5, making sure that g is primitive root of + * q-group */ + if (EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, DH_GENERATOR_5) <= 0) { + RNP_LOG("Failed to set key generator: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_paramgen(ctx, &parmkey) <= 0) { + RNP_LOG("Failed to generate parameters: %lu", ERR_peek_last_error()); + goto done; + } + EVP_PKEY_CTX_free(ctx); + /* Generate DH (ElGamal) key */ +start: + ctx = EVP_PKEY_CTX_new(parmkey, NULL); + if (!ctx) { + RNP_LOG("Failed to create ctx: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_keygen_init(ctx) <= 0) { + RNP_LOG("Failed to init keygen: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + RNP_LOG("ElGamal keygen failed: %lu", ERR_peek_last_error()); + goto done; + } + dh = EVP_PKEY_get0_DH(pkey); + if (!dh) { + RNP_LOG("Failed to retrieve DH key: %lu", ERR_peek_last_error()); + goto done; + } + if (BITS_TO_BYTES(BN_num_bits(DH_get0_pub_key(dh))) != BITS_TO_BYTES(keybits)) { + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + goto start; + } + + const bignum_t *p; + const bignum_t *g; + const bignum_t *y; + const bignum_t *x; + p = DH_get0_p(dh); + g = DH_get0_g(dh); + y = DH_get0_pub_key(dh); + x = DH_get0_priv_key(dh); + if (!p || !g || !y || !x) { + ret = RNP_ERROR_BAD_STATE; + goto done; + } + bn2mpi(p, &key->p); + bn2mpi(g, &key->g); + bn2mpi(y, &key->y); + bn2mpi(x, &key->x); + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(parmkey); + EVP_PKEY_free(pkey); + return ret; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash_common.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash_common.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash_common.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash_common.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "hash.h" +#include "types.h" +#include "utils.h" +#include "str-utils.h" + +static const struct hash_alg_map_t { + pgp_hash_alg_t type; + const char * name; + size_t len; +} hash_alg_map[] = {{PGP_HASH_MD5, "MD5", 16}, + {PGP_HASH_SHA1, "SHA1", 20}, + {PGP_HASH_RIPEMD, "RIPEMD160", 20}, + {PGP_HASH_SHA256, "SHA256", 32}, + {PGP_HASH_SHA384, "SHA384", 48}, + {PGP_HASH_SHA512, "SHA512", 64}, + {PGP_HASH_SHA224, "SHA224", 28}, + {PGP_HASH_SM3, "SM3", 32}, + {PGP_HASH_SHA3_256, "SHA3-256", 32}, + {PGP_HASH_SHA3_512, "SHA3-512", 64}}; + +namespace rnp { + +pgp_hash_alg_t +Hash::alg() const +{ + return alg_; +} + +size_t +Hash::size() const +{ + return size_; +} + +void +Hash::add(uint32_t val) +{ + uint8_t ibuf[4]; + STORE32BE(ibuf, val); + add(ibuf, sizeof(ibuf)); +} + +void +Hash::add(const pgp_mpi_t &val) +{ + size_t len = mpi_bytes(&val); + size_t idx = 0; + while ((idx < len) && (!val.mpi[idx])) { + idx++; + } + + if (idx >= len) { + add(0); + return; + } + + add(len - idx); + if (val.mpi[idx] & 0x80) { + uint8_t padbyte = 0; + add(&padbyte, 1); + } + add(val.mpi + idx, len - idx); +} + +pgp_hash_alg_t +Hash::alg(const char *name) +{ + if (!name) { + return PGP_HASH_UNKNOWN; + } + for (size_t i = 0; i < ARRAY_SIZE(hash_alg_map); i++) { + if (rnp::str_case_eq(name, hash_alg_map[i].name)) { + return hash_alg_map[i].type; + } + } + return PGP_HASH_UNKNOWN; +} + +const char * +Hash::name(pgp_hash_alg_t alg) +{ + const char *ret = NULL; + ARRAY_LOOKUP_BY_ID(hash_alg_map, type, name, alg, ret); + return ret; +} + +size_t +Hash::size(pgp_hash_alg_t alg) +{ + size_t val = 0; + ARRAY_LOOKUP_BY_ID(hash_alg_map, type, len, alg, val); + return val; +} + +Hash::Hash(Hash &&src) +{ + handle_ = src.handle_; + src.handle_ = NULL; + alg_ = src.alg_; + src.alg_ = PGP_HASH_UNKNOWN; + size_ = src.size_; + src.size_ = 0; +} + +Hash & +Hash::operator=(const Hash &src) +{ + src.clone(*this); + return *this; +} + +Hash & +Hash::operator=(Hash &&src) +{ + if (handle_) { + finish(); + } + handle_ = src.handle_; + src.handle_ = NULL; + alg_ = src.alg_; + src.alg_ = PGP_HASH_UNKNOWN; + size_ = src.size_; + src.size_ = 0; + return *this; +} + +void +HashList::add_alg(pgp_hash_alg_t alg) +{ + if (!get(alg)) { + hashes_.emplace_back(alg); + } +} + +const Hash * +HashList::get(pgp_hash_alg_t alg) const +{ + for (auto &hash : hashes_) { + if (hash.alg() == alg) { + return &hash; + } + } + return NULL; +} + +void +HashList::add(const void *buf, size_t len) +{ + for (auto &hash : hashes_) { + hash.add(buf, len); + } +} + +bool +HashList::empty() const +{ + return hashes_.empty(); +} + +std::vector & +HashList::hashes() +{ + return hashes_; +} + +} // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -1,36 +1,7 @@ -/*- - * Copyright (c) 2017-2019 Ribose Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. +/* + * Copyright (c) 2017-2021 Ribose Inc. * All rights reserved. * - * This code is derived from software contributed to The NetBSD Foundation - * by Alistair Crooks (agc@NetBSD.org) - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -52,26 +23,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ #include #include @@ -79,258 +30,171 @@ #include "hash.h" #include "types.h" #include "utils.h" +#include "str-utils.h" #include "defaults.h" +#include "sha1cd/hash_sha1cd.h" -static const struct hash_alg_map_t { - pgp_hash_alg_t type; - const char * name; - const char * botan_name; - size_t digest_size; -} hash_alg_map[] = {{PGP_HASH_MD5, "MD5", "MD5", 16}, - {PGP_HASH_SHA1, "SHA1", "SHA-1", 20}, - {PGP_HASH_RIPEMD, "RIPEMD160", "RIPEMD-160", 20}, - {PGP_HASH_SHA256, "SHA256", "SHA-256", 32}, - {PGP_HASH_SHA384, "SHA384", "SHA-384", 48}, - {PGP_HASH_SHA512, "SHA512", "SHA-512", 64}, - {PGP_HASH_SHA224, "SHA224", "SHA-224", 28}, - {PGP_HASH_SM3, "SM3", "SM3", 32}, - {PGP_HASH_SHA3_256, "SHA3-256", "SHA-3(256)", 32}, - {PGP_HASH_SHA3_512, "SHA3-512", "SHA-3(512)", 64}}; -/** - * \ingroup Core_Print - * - * returns description of the Hash Algorithm type - * \param hash Hash Algorithm type - * \return string or "Unknown" - */ -const char * -pgp_show_hash_alg(uint8_t hash) -{ - const char *ret = NULL; - ARRAY_LOOKUP_BY_ID(hash_alg_map, type, name, hash, ret); - return ret; -} - -const char * -pgp_hash_name_botan(pgp_hash_alg_t hash) -{ - const char *ret = NULL; - ARRAY_LOOKUP_BY_ID(hash_alg_map, type, botan_name, hash, ret); - return ret; -} - -const char * -pgp_hash_name(const pgp_hash_t *hash) -{ - return pgp_show_hash_alg(hash->_alg); -} - -/** -\ingroup Core_Hashes -\brief Returns hash enum corresponding to given string -\param hash Text name of hash algorithm i.e. "SHA1" -\returns Corresponding enum i.e. PGP_HASH_SHA1 -*/ -pgp_hash_alg_t -pgp_str_to_hash_alg(const char *hash) -{ - if (hash == NULL) { - return DEFAULT_PGP_HASH_ALG; - } - for (size_t i = 0; i < ARRAY_SIZE(hash_alg_map); i++) { - if (!rnp_strcasecmp(hash, hash_alg_map[i].name)) { - return hash_alg_map[i].type; +static const id_str_pair botan_alg_map[] = { + {PGP_HASH_MD5, "MD5"}, + {PGP_HASH_SHA1, "SHA-1"}, + {PGP_HASH_RIPEMD, "RIPEMD-160"}, + {PGP_HASH_SHA256, "SHA-256"}, + {PGP_HASH_SHA384, "SHA-384"}, + {PGP_HASH_SHA512, "SHA-512"}, + {PGP_HASH_SHA224, "SHA-224"}, + {PGP_HASH_SM3, "SM3"}, + {PGP_HASH_SHA3_256, "SHA-3(256)"}, + {PGP_HASH_SHA3_512, "SHA-3(512)"}, + {0, NULL}, +}; + +namespace rnp { + +Hash::Hash(pgp_hash_alg_t alg) +{ + if (alg == PGP_HASH_SHA1) { + /* todo: avoid duplication here and in the OpenSSL backend */ + handle_ = hash_sha1cd_create(); + if (!handle_) { + throw rnp_exception(RNP_ERROR_OUT_OF_MEMORY); } + alg_ = alg; + size_ = rnp::Hash::size(alg); + return; } - return PGP_HASH_UNKNOWN; -} -static bool -botan_hash_create(pgp_hash_t *hash, const char *hash_name) -{ - if (!hash_name) { - return false; + const char *name = Hash::name_backend(alg); + if (!name) { + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - std::unique_ptr hash_fn; - try { - hash_fn = Botan::HashFunction::create(hash_name); - } catch (std::exception &ex) { - RNP_LOG("Error creating HashFunction ('%s')", ex.what()); - } + auto hash_fn = Botan::HashFunction::create(name); if (!hash_fn) { - RNP_LOG("Error creating hash object for '%s'", hash_name); - return false; + RNP_LOG("Error creating hash object for '%s'", name); + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - hash->_output_len = hash_fn->output_length(); - if (hash->_output_len == 0) { - RNP_LOG("In pgp_hash_create, botan_hash_output_length failed"); - return false; + size_ = hash_fn->output_length(); + if (!size_) { + RNP_LOG("output_length() call failed"); + throw rnp_exception(RNP_ERROR_BAD_STATE); } - - hash->handle = hash_fn.release(); - return true; + handle_ = hash_fn.release(); + alg_ = alg; } -/** -\ingroup Core_Hashes -\brief Setup hash for given hash algorithm -\param hash Hash to set up -\param alg Hash algorithm to use -*/ -bool -pgp_hash_create(pgp_hash_t *hash, pgp_hash_alg_t alg) +void +Hash::add(const void *buf, size_t len) { - if (!botan_hash_create(hash, pgp_hash_name_botan(alg))) { - return false; + if (!handle_) { + throw rnp_exception(RNP_ERROR_NULL_POINTER); } - - hash->_alg = alg; - return true; -} - -bool -pgp_hash_create_crc24(pgp_hash_t *hash) -{ - if (!botan_hash_create(hash, "CRC24")) { - return false; + if (alg_ == PGP_HASH_SHA1) { + hash_sha1cd_add(handle_, buf, len); + return; } - - hash->_alg = PGP_HASH_UNKNOWN; - return true; + static_cast(handle_)->update(static_cast(buf), + len); } -bool -pgp_hash_copy(pgp_hash_t *dst, const pgp_hash_t *src) +size_t +Hash::finish(uint8_t *digest) { - if (!src || !dst) { - return false; + if (!handle_) { + return 0; + } + if (alg_ == PGP_HASH_SHA1) { + int res = hash_sha1cd_finish(handle_, digest); + handle_ = NULL; + size_ = 0; + if (res) { + throw rnp_exception(RNP_ERROR_BAD_STATE); + } + return 20; } - Botan::HashFunction *hash_fn = static_cast(src->handle); + auto hash_fn = + std::unique_ptr(static_cast(handle_)); if (!hash_fn) { - return false; + RNP_LOG("Hash finalization failed"); + throw rnp_exception(RNP_ERROR_BAD_STATE); } - std::unique_ptr handle; - try { - handle = hash_fn->copy_state(); - } catch (std::exception &ex) { - RNP_LOG("Error copying HashFunction ('%s')", ex.what()); - } - if (!handle) { - return false; - } + size_t outlen = size_; + handle_ = NULL; + size_ = 0; - dst->_output_len = src->_output_len; - dst->_alg = src->_alg; - dst->handle = handle.release(); - return true; + if (digest) { + hash_fn->final(digest); + } + return outlen; } -int -pgp_hash_add(pgp_hash_t *hash, const void *buf, size_t len) +void +Hash::clone(Hash &dst) const { - if (!hash->handle) { - return -1; + if (!handle_) { + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - try { - static_cast(hash->handle) - ->update(static_cast(buf), len); - } catch (std::exception &ex) { - RNP_LOG("Error adding to HashFunction ('%s')", ex.what()); - return -2; + if (dst.handle_) { + dst.finish(); } - return 0; -} -size_t -pgp_hash_finish(pgp_hash_t *hash, uint8_t *out) -{ - if (!hash || !hash->handle) { - return 0; + if (alg_ == PGP_HASH_SHA1) { + dst.handle_ = hash_sha1cd_clone(handle_); + if (!dst.handle_) { + throw rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + dst.size_ = size_; + dst.alg_ = alg_; + return; } - Botan::HashFunction *hash_fn = static_cast(hash->handle); + auto hash_fn = static_cast(handle_); if (!hash_fn) { - RNP_LOG("Hash finalization failed"); - return 0; + throw rnp_exception(RNP_ERROR_BAD_STATE); } - size_t outlen = hash->_output_len; - hash->handle = NULL; - try { - if (out) { - hash_fn->final(out); - } - delete hash_fn; - } catch (std::exception &ex) { - RNP_LOG("Error finishing HashFunction ('%s')", ex.what()); - outlen = 0; + auto copy = hash_fn->copy_state(); + if (!copy) { + RNP_LOG("Failed to clone hash."); + throw rnp_exception(RNP_ERROR_BAD_STATE); } - hash->_output_len = 0; - return outlen; -} -pgp_hash_alg_t -pgp_hash_alg_type(const pgp_hash_t *hash) -{ - return hash->_alg; + dst.size_ = size_; + dst.alg_ = alg_; + dst.handle_ = copy.release(); } -size_t -pgp_digest_length(pgp_hash_alg_t alg) +Hash::~Hash() { - size_t val = 0; - ARRAY_LOOKUP_BY_ID(hash_alg_map, type, digest_size, alg, val); - return val; -} - -bool -pgp_hash_list_add(std::vector &hashes, pgp_hash_alg_t alg) -{ - pgp_hash_t hash = {0}; - if (!pgp_hash_list_get(hashes, alg)) { - if (!pgp_hash_create(&hash, alg)) { - RNP_LOG("failed to initialize hash algorithm %d", (int) alg); - return false; - } - try { - hashes.push_back(hash); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - pgp_hash_finish(&hash, NULL); - return false; - } + if (!handle_) { + return; } - return true; -} - -const pgp_hash_t * -pgp_hash_list_get(std::vector &hashes, pgp_hash_alg_t alg) -{ - for (auto &hash : hashes) { - if (pgp_hash_alg_type(&hash) == alg) { - return &hash; - } + if (alg_ == PGP_HASH_SHA1) { + hash_sha1cd_finish(handle_, NULL); + } else { + delete static_cast(handle_); } - return NULL; } -void -pgp_hash_list_update(std::vector &hashes, const void *buf, size_t len) +CRC24::CRC24() { - for (auto &hash : hashes) { - pgp_hash_add(&hash, buf, len); + auto hash_fn = Botan::HashFunction::create("CRC24"); + if (!hash_fn) { + RNP_LOG("Error creating hash object for 'CRC24'"); + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); } + + size_ = 3; + alg_ = PGP_HASH_UNKNOWN; + handle_ = hash_fn.release(); } -bool -pgp_hash_uint32(pgp_hash_t *hash, uint32_t n) +const char * +Hash::name_backend(pgp_hash_alg_t alg) { - uint8_t ibuf[4]; - STORE32BE(ibuf, n); - return !pgp_hash_add(hash, ibuf, sizeof(ibuf)); + return id_str_pair::lookup(botan_alg_map, alg); } +} // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash_crc24.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash_crc24.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash_crc24.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash_crc24.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2017-2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "utils.h" +#include "hash.h" + +static const uint32_t T0[256] = { + 0x00000000, 0x00FB4C86, 0x000DD58A, 0x00F6990C, 0x00E1E693, 0x001AAA15, 0x00EC3319, + 0x00177F9F, 0x003981A1, 0x00C2CD27, 0x0034542B, 0x00CF18AD, 0x00D86732, 0x00232BB4, + 0x00D5B2B8, 0x002EFE3E, 0x00894EC5, 0x00720243, 0x00849B4F, 0x007FD7C9, 0x0068A856, + 0x0093E4D0, 0x00657DDC, 0x009E315A, 0x00B0CF64, 0x004B83E2, 0x00BD1AEE, 0x00465668, + 0x005129F7, 0x00AA6571, 0x005CFC7D, 0x00A7B0FB, 0x00E9D10C, 0x00129D8A, 0x00E40486, + 0x001F4800, 0x0008379F, 0x00F37B19, 0x0005E215, 0x00FEAE93, 0x00D050AD, 0x002B1C2B, + 0x00DD8527, 0x0026C9A1, 0x0031B63E, 0x00CAFAB8, 0x003C63B4, 0x00C72F32, 0x00609FC9, + 0x009BD34F, 0x006D4A43, 0x009606C5, 0x0081795A, 0x007A35DC, 0x008CACD0, 0x0077E056, + 0x00591E68, 0x00A252EE, 0x0054CBE2, 0x00AF8764, 0x00B8F8FB, 0x0043B47D, 0x00B52D71, + 0x004E61F7, 0x00D2A319, 0x0029EF9F, 0x00DF7693, 0x00243A15, 0x0033458A, 0x00C8090C, + 0x003E9000, 0x00C5DC86, 0x00EB22B8, 0x00106E3E, 0x00E6F732, 0x001DBBB4, 0x000AC42B, + 0x00F188AD, 0x000711A1, 0x00FC5D27, 0x005BEDDC, 0x00A0A15A, 0x00563856, 0x00AD74D0, + 0x00BA0B4F, 0x004147C9, 0x00B7DEC5, 0x004C9243, 0x00626C7D, 0x009920FB, 0x006FB9F7, + 0x0094F571, 0x00838AEE, 0x0078C668, 0x008E5F64, 0x007513E2, 0x003B7215, 0x00C03E93, + 0x0036A79F, 0x00CDEB19, 0x00DA9486, 0x0021D800, 0x00D7410C, 0x002C0D8A, 0x0002F3B4, + 0x00F9BF32, 0x000F263E, 0x00F46AB8, 0x00E31527, 0x001859A1, 0x00EEC0AD, 0x00158C2B, + 0x00B23CD0, 0x00497056, 0x00BFE95A, 0x0044A5DC, 0x0053DA43, 0x00A896C5, 0x005E0FC9, + 0x00A5434F, 0x008BBD71, 0x0070F1F7, 0x008668FB, 0x007D247D, 0x006A5BE2, 0x00911764, + 0x00678E68, 0x009CC2EE, 0x00A44733, 0x005F0BB5, 0x00A992B9, 0x0052DE3F, 0x0045A1A0, + 0x00BEED26, 0x0048742A, 0x00B338AC, 0x009DC692, 0x00668A14, 0x00901318, 0x006B5F9E, + 0x007C2001, 0x00876C87, 0x0071F58B, 0x008AB90D, 0x002D09F6, 0x00D64570, 0x0020DC7C, + 0x00DB90FA, 0x00CCEF65, 0x0037A3E3, 0x00C13AEF, 0x003A7669, 0x00148857, 0x00EFC4D1, + 0x00195DDD, 0x00E2115B, 0x00F56EC4, 0x000E2242, 0x00F8BB4E, 0x0003F7C8, 0x004D963F, + 0x00B6DAB9, 0x004043B5, 0x00BB0F33, 0x00AC70AC, 0x00573C2A, 0x00A1A526, 0x005AE9A0, + 0x0074179E, 0x008F5B18, 0x0079C214, 0x00828E92, 0x0095F10D, 0x006EBD8B, 0x00982487, + 0x00636801, 0x00C4D8FA, 0x003F947C, 0x00C90D70, 0x003241F6, 0x00253E69, 0x00DE72EF, + 0x0028EBE3, 0x00D3A765, 0x00FD595B, 0x000615DD, 0x00F08CD1, 0x000BC057, 0x001CBFC8, + 0x00E7F34E, 0x00116A42, 0x00EA26C4, 0x0076E42A, 0x008DA8AC, 0x007B31A0, 0x00807D26, + 0x009702B9, 0x006C4E3F, 0x009AD733, 0x00619BB5, 0x004F658B, 0x00B4290D, 0x0042B001, + 0x00B9FC87, 0x00AE8318, 0x0055CF9E, 0x00A35692, 0x00581A14, 0x00FFAAEF, 0x0004E669, + 0x00F27F65, 0x000933E3, 0x001E4C7C, 0x00E500FA, 0x001399F6, 0x00E8D570, 0x00C62B4E, + 0x003D67C8, 0x00CBFEC4, 0x0030B242, 0x0027CDDD, 0x00DC815B, 0x002A1857, 0x00D154D1, + 0x009F3526, 0x006479A0, 0x0092E0AC, 0x0069AC2A, 0x007ED3B5, 0x00859F33, 0x0073063F, + 0x00884AB9, 0x00A6B487, 0x005DF801, 0x00AB610D, 0x00502D8B, 0x00475214, 0x00BC1E92, + 0x004A879E, 0x00B1CB18, 0x00167BE3, 0x00ED3765, 0x001BAE69, 0x00E0E2EF, 0x00F79D70, + 0x000CD1F6, 0x00FA48FA, 0x0001047C, 0x002FFA42, 0x00D4B6C4, 0x00222FC8, 0x00D9634E, + 0x00CE1CD1, 0x00355057, 0x00C3C95B, 0x003885DD, +}; + +static const uint32_t T1[256] = { + 0x00000000, 0x00488F66, 0x00901ECD, 0x00D891AB, 0x00DB711C, 0x0093FE7A, 0x004B6FD1, + 0x0003E0B7, 0x00B6E338, 0x00FE6C5E, 0x0026FDF5, 0x006E7293, 0x006D9224, 0x00251D42, + 0x00FD8CE9, 0x00B5038F, 0x006CC771, 0x00244817, 0x00FCD9BC, 0x00B456DA, 0x00B7B66D, + 0x00FF390B, 0x0027A8A0, 0x006F27C6, 0x00DA2449, 0x0092AB2F, 0x004A3A84, 0x0002B5E2, + 0x00015555, 0x0049DA33, 0x00914B98, 0x00D9C4FE, 0x00D88EE3, 0x00900185, 0x0048902E, + 0x00001F48, 0x0003FFFF, 0x004B7099, 0x0093E132, 0x00DB6E54, 0x006E6DDB, 0x0026E2BD, + 0x00FE7316, 0x00B6FC70, 0x00B51CC7, 0x00FD93A1, 0x0025020A, 0x006D8D6C, 0x00B44992, + 0x00FCC6F4, 0x0024575F, 0x006CD839, 0x006F388E, 0x0027B7E8, 0x00FF2643, 0x00B7A925, + 0x0002AAAA, 0x004A25CC, 0x0092B467, 0x00DA3B01, 0x00D9DBB6, 0x009154D0, 0x0049C57B, + 0x00014A1D, 0x004B5141, 0x0003DE27, 0x00DB4F8C, 0x0093C0EA, 0x0090205D, 0x00D8AF3B, + 0x00003E90, 0x0048B1F6, 0x00FDB279, 0x00B53D1F, 0x006DACB4, 0x002523D2, 0x0026C365, + 0x006E4C03, 0x00B6DDA8, 0x00FE52CE, 0x00279630, 0x006F1956, 0x00B788FD, 0x00FF079B, + 0x00FCE72C, 0x00B4684A, 0x006CF9E1, 0x00247687, 0x00917508, 0x00D9FA6E, 0x00016BC5, + 0x0049E4A3, 0x004A0414, 0x00028B72, 0x00DA1AD9, 0x009295BF, 0x0093DFA2, 0x00DB50C4, + 0x0003C16F, 0x004B4E09, 0x0048AEBE, 0x000021D8, 0x00D8B073, 0x00903F15, 0x00253C9A, + 0x006DB3FC, 0x00B52257, 0x00FDAD31, 0x00FE4D86, 0x00B6C2E0, 0x006E534B, 0x0026DC2D, + 0x00FF18D3, 0x00B797B5, 0x006F061E, 0x00278978, 0x002469CF, 0x006CE6A9, 0x00B47702, + 0x00FCF864, 0x0049FBEB, 0x0001748D, 0x00D9E526, 0x00916A40, 0x00928AF7, 0x00DA0591, + 0x0002943A, 0x004A1B5C, 0x0096A282, 0x00DE2DE4, 0x0006BC4F, 0x004E3329, 0x004DD39E, + 0x00055CF8, 0x00DDCD53, 0x00954235, 0x002041BA, 0x0068CEDC, 0x00B05F77, 0x00F8D011, + 0x00FB30A6, 0x00B3BFC0, 0x006B2E6B, 0x0023A10D, 0x00FA65F3, 0x00B2EA95, 0x006A7B3E, + 0x0022F458, 0x002114EF, 0x00699B89, 0x00B10A22, 0x00F98544, 0x004C86CB, 0x000409AD, + 0x00DC9806, 0x00941760, 0x0097F7D7, 0x00DF78B1, 0x0007E91A, 0x004F667C, 0x004E2C61, + 0x0006A307, 0x00DE32AC, 0x0096BDCA, 0x00955D7D, 0x00DDD21B, 0x000543B0, 0x004DCCD6, + 0x00F8CF59, 0x00B0403F, 0x0068D194, 0x00205EF2, 0x0023BE45, 0x006B3123, 0x00B3A088, + 0x00FB2FEE, 0x0022EB10, 0x006A6476, 0x00B2F5DD, 0x00FA7ABB, 0x00F99A0C, 0x00B1156A, + 0x006984C1, 0x00210BA7, 0x00940828, 0x00DC874E, 0x000416E5, 0x004C9983, 0x004F7934, + 0x0007F652, 0x00DF67F9, 0x0097E89F, 0x00DDF3C3, 0x00957CA5, 0x004DED0E, 0x00056268, + 0x000682DF, 0x004E0DB9, 0x00969C12, 0x00DE1374, 0x006B10FB, 0x00239F9D, 0x00FB0E36, + 0x00B38150, 0x00B061E7, 0x00F8EE81, 0x00207F2A, 0x0068F04C, 0x00B134B2, 0x00F9BBD4, + 0x00212A7F, 0x0069A519, 0x006A45AE, 0x0022CAC8, 0x00FA5B63, 0x00B2D405, 0x0007D78A, + 0x004F58EC, 0x0097C947, 0x00DF4621, 0x00DCA696, 0x009429F0, 0x004CB85B, 0x0004373D, + 0x00057D20, 0x004DF246, 0x009563ED, 0x00DDEC8B, 0x00DE0C3C, 0x0096835A, 0x004E12F1, + 0x00069D97, 0x00B39E18, 0x00FB117E, 0x002380D5, 0x006B0FB3, 0x0068EF04, 0x00206062, + 0x00F8F1C9, 0x00B07EAF, 0x0069BA51, 0x00213537, 0x00F9A49C, 0x00B12BFA, 0x00B2CB4D, + 0x00FA442B, 0x0022D580, 0x006A5AE6, 0x00DF5969, 0x0097D60F, 0x004F47A4, 0x0007C8C2, + 0x00042875, 0x004CA713, 0x009436B8, 0x00DCB9DE, +}; + +static const uint32_t T2[256] = { + 0x00000000, 0x00D70983, 0x00555F80, 0x00825603, 0x0051F286, 0x0086FB05, 0x0004AD06, + 0x00D3A485, 0x0059A88B, 0x008EA108, 0x000CF70B, 0x00DBFE88, 0x00085A0D, 0x00DF538E, + 0x005D058D, 0x008A0C0E, 0x00491C91, 0x009E1512, 0x001C4311, 0x00CB4A92, 0x0018EE17, + 0x00CFE794, 0x004DB197, 0x009AB814, 0x0010B41A, 0x00C7BD99, 0x0045EB9A, 0x0092E219, + 0x0041469C, 0x00964F1F, 0x0014191C, 0x00C3109F, 0x006974A4, 0x00BE7D27, 0x003C2B24, + 0x00EB22A7, 0x00388622, 0x00EF8FA1, 0x006DD9A2, 0x00BAD021, 0x0030DC2F, 0x00E7D5AC, + 0x006583AF, 0x00B28A2C, 0x00612EA9, 0x00B6272A, 0x00347129, 0x00E378AA, 0x00206835, + 0x00F761B6, 0x007537B5, 0x00A23E36, 0x00719AB3, 0x00A69330, 0x0024C533, 0x00F3CCB0, + 0x0079C0BE, 0x00AEC93D, 0x002C9F3E, 0x00FB96BD, 0x00283238, 0x00FF3BBB, 0x007D6DB8, + 0x00AA643B, 0x0029A4CE, 0x00FEAD4D, 0x007CFB4E, 0x00ABF2CD, 0x00785648, 0x00AF5FCB, + 0x002D09C8, 0x00FA004B, 0x00700C45, 0x00A705C6, 0x002553C5, 0x00F25A46, 0x0021FEC3, + 0x00F6F740, 0x0074A143, 0x00A3A8C0, 0x0060B85F, 0x00B7B1DC, 0x0035E7DF, 0x00E2EE5C, + 0x00314AD9, 0x00E6435A, 0x00641559, 0x00B31CDA, 0x003910D4, 0x00EE1957, 0x006C4F54, + 0x00BB46D7, 0x0068E252, 0x00BFEBD1, 0x003DBDD2, 0x00EAB451, 0x0040D06A, 0x0097D9E9, + 0x00158FEA, 0x00C28669, 0x001122EC, 0x00C62B6F, 0x00447D6C, 0x009374EF, 0x001978E1, + 0x00CE7162, 0x004C2761, 0x009B2EE2, 0x00488A67, 0x009F83E4, 0x001DD5E7, 0x00CADC64, + 0x0009CCFB, 0x00DEC578, 0x005C937B, 0x008B9AF8, 0x00583E7D, 0x008F37FE, 0x000D61FD, + 0x00DA687E, 0x00506470, 0x00876DF3, 0x00053BF0, 0x00D23273, 0x000196F6, 0x00D69F75, + 0x0054C976, 0x0083C0F5, 0x00A9041B, 0x007E0D98, 0x00FC5B9B, 0x002B5218, 0x00F8F69D, + 0x002FFF1E, 0x00ADA91D, 0x007AA09E, 0x00F0AC90, 0x0027A513, 0x00A5F310, 0x0072FA93, + 0x00A15E16, 0x00765795, 0x00F40196, 0x00230815, 0x00E0188A, 0x00371109, 0x00B5470A, + 0x00624E89, 0x00B1EA0C, 0x0066E38F, 0x00E4B58C, 0x0033BC0F, 0x00B9B001, 0x006EB982, + 0x00ECEF81, 0x003BE602, 0x00E84287, 0x003F4B04, 0x00BD1D07, 0x006A1484, 0x00C070BF, + 0x0017793C, 0x00952F3F, 0x004226BC, 0x00918239, 0x00468BBA, 0x00C4DDB9, 0x0013D43A, + 0x0099D834, 0x004ED1B7, 0x00CC87B4, 0x001B8E37, 0x00C82AB2, 0x001F2331, 0x009D7532, + 0x004A7CB1, 0x00896C2E, 0x005E65AD, 0x00DC33AE, 0x000B3A2D, 0x00D89EA8, 0x000F972B, + 0x008DC128, 0x005AC8AB, 0x00D0C4A5, 0x0007CD26, 0x00859B25, 0x005292A6, 0x00813623, + 0x00563FA0, 0x00D469A3, 0x00036020, 0x0080A0D5, 0x0057A956, 0x00D5FF55, 0x0002F6D6, + 0x00D15253, 0x00065BD0, 0x00840DD3, 0x00530450, 0x00D9085E, 0x000E01DD, 0x008C57DE, + 0x005B5E5D, 0x0088FAD8, 0x005FF35B, 0x00DDA558, 0x000AACDB, 0x00C9BC44, 0x001EB5C7, + 0x009CE3C4, 0x004BEA47, 0x00984EC2, 0x004F4741, 0x00CD1142, 0x001A18C1, 0x009014CF, + 0x00471D4C, 0x00C54B4F, 0x001242CC, 0x00C1E649, 0x0016EFCA, 0x0094B9C9, 0x0043B04A, + 0x00E9D471, 0x003EDDF2, 0x00BC8BF1, 0x006B8272, 0x00B826F7, 0x006F2F74, 0x00ED7977, + 0x003A70F4, 0x00B07CFA, 0x00677579, 0x00E5237A, 0x00322AF9, 0x00E18E7C, 0x003687FF, + 0x00B4D1FC, 0x0063D87F, 0x00A0C8E0, 0x0077C163, 0x00F59760, 0x00229EE3, 0x00F13A66, + 0x002633E5, 0x00A465E6, 0x00736C65, 0x00F9606B, 0x002E69E8, 0x00AC3FEB, 0x007B3668, + 0x00A892ED, 0x007F9B6E, 0x00FDCD6D, 0x002AC4EE, +}; + +static const uint32_t T3[256] = { + 0x00000000, 0x00520936, 0x00A4126C, 0x00F61B5A, 0x004825D8, 0x001A2CEE, 0x00EC37B4, + 0x00BE3E82, 0x006B0636, 0x00390F00, 0x00CF145A, 0x009D1D6C, 0x002323EE, 0x00712AD8, + 0x00873182, 0x00D538B4, 0x00D60C6C, 0x0084055A, 0x00721E00, 0x00201736, 0x009E29B4, + 0x00CC2082, 0x003A3BD8, 0x006832EE, 0x00BD0A5A, 0x00EF036C, 0x00191836, 0x004B1100, + 0x00F52F82, 0x00A726B4, 0x00513DEE, 0x000334D8, 0x00AC19D8, 0x00FE10EE, 0x00080BB4, + 0x005A0282, 0x00E43C00, 0x00B63536, 0x00402E6C, 0x0012275A, 0x00C71FEE, 0x009516D8, + 0x00630D82, 0x003104B4, 0x008F3A36, 0x00DD3300, 0x002B285A, 0x0079216C, 0x007A15B4, + 0x00281C82, 0x00DE07D8, 0x008C0EEE, 0x0032306C, 0x0060395A, 0x00962200, 0x00C42B36, + 0x00111382, 0x00431AB4, 0x00B501EE, 0x00E708D8, 0x0059365A, 0x000B3F6C, 0x00FD2436, + 0x00AF2D00, 0x00A37F36, 0x00F17600, 0x00076D5A, 0x0055646C, 0x00EB5AEE, 0x00B953D8, + 0x004F4882, 0x001D41B4, 0x00C87900, 0x009A7036, 0x006C6B6C, 0x003E625A, 0x00805CD8, + 0x00D255EE, 0x00244EB4, 0x00764782, 0x0075735A, 0x00277A6C, 0x00D16136, 0x00836800, + 0x003D5682, 0x006F5FB4, 0x009944EE, 0x00CB4DD8, 0x001E756C, 0x004C7C5A, 0x00BA6700, + 0x00E86E36, 0x005650B4, 0x00045982, 0x00F242D8, 0x00A04BEE, 0x000F66EE, 0x005D6FD8, + 0x00AB7482, 0x00F97DB4, 0x00474336, 0x00154A00, 0x00E3515A, 0x00B1586C, 0x006460D8, + 0x003669EE, 0x00C072B4, 0x00927B82, 0x002C4500, 0x007E4C36, 0x0088576C, 0x00DA5E5A, + 0x00D96A82, 0x008B63B4, 0x007D78EE, 0x002F71D8, 0x00914F5A, 0x00C3466C, 0x00355D36, + 0x00675400, 0x00B26CB4, 0x00E06582, 0x00167ED8, 0x004477EE, 0x00FA496C, 0x00A8405A, + 0x005E5B00, 0x000C5236, 0x0046FF6C, 0x0014F65A, 0x00E2ED00, 0x00B0E436, 0x000EDAB4, + 0x005CD382, 0x00AAC8D8, 0x00F8C1EE, 0x002DF95A, 0x007FF06C, 0x0089EB36, 0x00DBE200, + 0x0065DC82, 0x0037D5B4, 0x00C1CEEE, 0x0093C7D8, 0x0090F300, 0x00C2FA36, 0x0034E16C, + 0x0066E85A, 0x00D8D6D8, 0x008ADFEE, 0x007CC4B4, 0x002ECD82, 0x00FBF536, 0x00A9FC00, + 0x005FE75A, 0x000DEE6C, 0x00B3D0EE, 0x00E1D9D8, 0x0017C282, 0x0045CBB4, 0x00EAE6B4, + 0x00B8EF82, 0x004EF4D8, 0x001CFDEE, 0x00A2C36C, 0x00F0CA5A, 0x0006D100, 0x0054D836, + 0x0081E082, 0x00D3E9B4, 0x0025F2EE, 0x0077FBD8, 0x00C9C55A, 0x009BCC6C, 0x006DD736, + 0x003FDE00, 0x003CEAD8, 0x006EE3EE, 0x0098F8B4, 0x00CAF182, 0x0074CF00, 0x0026C636, + 0x00D0DD6C, 0x0082D45A, 0x0057ECEE, 0x0005E5D8, 0x00F3FE82, 0x00A1F7B4, 0x001FC936, + 0x004DC000, 0x00BBDB5A, 0x00E9D26C, 0x00E5805A, 0x00B7896C, 0x00419236, 0x00139B00, + 0x00ADA582, 0x00FFACB4, 0x0009B7EE, 0x005BBED8, 0x008E866C, 0x00DC8F5A, 0x002A9400, + 0x00789D36, 0x00C6A3B4, 0x0094AA82, 0x0062B1D8, 0x0030B8EE, 0x00338C36, 0x00618500, + 0x00979E5A, 0x00C5976C, 0x007BA9EE, 0x0029A0D8, 0x00DFBB82, 0x008DB2B4, 0x00588A00, + 0x000A8336, 0x00FC986C, 0x00AE915A, 0x0010AFD8, 0x0042A6EE, 0x00B4BDB4, 0x00E6B482, + 0x00499982, 0x001B90B4, 0x00ED8BEE, 0x00BF82D8, 0x0001BC5A, 0x0053B56C, 0x00A5AE36, + 0x00F7A700, 0x00229FB4, 0x00709682, 0x00868DD8, 0x00D484EE, 0x006ABA6C, 0x0038B35A, + 0x00CEA800, 0x009CA136, 0x009F95EE, 0x00CD9CD8, 0x003B8782, 0x00698EB4, 0x00D7B036, + 0x0085B900, 0x0073A25A, 0x0021AB6C, 0x00F493D8, 0x00A69AEE, 0x005081B4, 0x00028882, + 0x00BCB600, 0x00EEBF36, 0x0018A46C, 0x004AAD5A}; + +#define CRC24_FAST_INIT 0xce04b7L + +static inline uint32_t +process8(uint32_t crc, uint8_t data) +{ + return (crc >> 8) ^ T0[(crc & 0xff) ^ data]; +} + +/* + * Process 4 bytes in one go + */ +static inline uint32_t +process32(uint32_t crc, uint32_t word) +{ + crc ^= word; + crc = T3[crc & 0xff] ^ T2[((crc >> 8) & 0xff)] ^ T1[((crc >> 16) & 0xff)] ^ + T0[(crc >> 24) & 0xff]; + return crc; +} + +static uint32_t +crc24_update(uint32_t crc, const uint8_t *in, size_t length) +{ + uint32_t d0, d1, d2, d3; + + while (length >= 16) { + LOAD32LE(d0, &in[0]); + LOAD32LE(d1, &in[4]); + LOAD32LE(d2, &in[8]); + LOAD32LE(d3, &in[12]); + + crc = process32(crc, d0); + crc = process32(crc, d1); + crc = process32(crc, d2); + crc = process32(crc, d3); + + in += 16; + length -= 16; + } + + while (length--) { + crc = process8(crc, *in++); + } + + return crc & 0xffffff; +} + +/* Swap endianness of 32-bit value */ +#if defined(__GNUC__) || defined(__clang__) +#define BSWAP32(x) __builtin_bswap32(x) +#else +#define BSWAP32(x) \ + ((x & 0x000000FF) << 24 | (x & 0x0000FF00) << 8 | (x & 0x00FF0000) >> 8 | \ + (x & 0xFF000000) >> 24) +#endif + +static uint32_t +crc24_final(uint32_t crc) +{ + return (BSWAP32(crc) >> 8); +} + +namespace rnp { + +CRC24::CRC24() +{ + state_ = CRC24_FAST_INIT; +} + +void +CRC24::add(const void *buf, size_t len) +{ + state_ = crc24_update(state_, static_cast(buf), len); +} + +size_t +CRC24::finish(uint8_t *crc) +{ + uint32_t crc_fin = crc24_final(state_); + state_ = 0; + if (crc) { + crc[0] = (crc_fin >> 16) & 0xff; + crc[1] = (crc_fin >> 8) & 0xff; + crc[2] = crc_fin & 0xff; + } + return 3; +} + +}; // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash.h 2022-04-15 07:49:21.000000000 +0000 @@ -1,12 +1,7 @@ /* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). - * Copyright (c) 2009 The NetBSD Foundation, Inc. + * Copyright (c) 2017-2021 Ribose Inc. * All rights reserved. * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and - * carried further by Ribose Inc (https://www.ribose.com). - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,83 +29,78 @@ #include #include "types.h" -#include "list.h" +#include "config.h" /** * Output size (in bytes) of biggest supported hash algo */ #define PGP_MAX_HASH_SIZE (64) -/** pgp_hash_t */ -typedef struct pgp_hash_t { - void * handle; /* hash object */ - size_t _output_len; - pgp_hash_alg_t _alg; /* algorithm */ -} pgp_hash_t; - -const char *pgp_hash_name_botan(const pgp_hash_alg_t alg); - -bool pgp_hash_create(pgp_hash_t *hash, pgp_hash_alg_t alg); -bool pgp_hash_create_crc24(pgp_hash_t *hash); -bool pgp_hash_copy(pgp_hash_t *dst, const pgp_hash_t *src); -int pgp_hash_add(pgp_hash_t *hash, const void *buf, size_t len); -size_t pgp_hash_finish(pgp_hash_t *hash, uint8_t *output); - -const char *pgp_hash_name(const pgp_hash_t *hash); - -pgp_hash_alg_t pgp_hash_alg_type(const pgp_hash_t *hash); - -pgp_hash_alg_t pgp_str_to_hash_alg(const char *); - -const char *pgp_show_hash_alg(uint8_t); - -/* @brief Returns output size of an digest algorithm - * - * @param hash alg - * - * @return size of the digest produced by the algorithm or 0 - * is not known - **/ -size_t pgp_digest_length(pgp_hash_alg_t alg); - -/* - * @brief Add hash for the corresponding algorithm to the list - * - * @param hashes non-NULL pointer to the list structure - * @param alg hash algorithm - * - * @return true if hash was added successfully or already exists in the list. - * false will be returned if memory allocation failed, or alg is not supported, or - * on other error - **/ -bool pgp_hash_list_add(std::vector &hashes, pgp_hash_alg_t alg); +namespace rnp { +class Hash { + protected: + void * handle_; + size_t size_; + pgp_hash_alg_t alg_; + + public: + pgp_hash_alg_t alg() const; + size_t size() const; + + Hash() : handle_(NULL), size_(0), alg_(PGP_HASH_UNKNOWN){}; + Hash(pgp_hash_alg_t alg); + Hash(Hash &&src); + + virtual void add(const void *buf, size_t len); + virtual void add(uint32_t val); + virtual void add(const pgp_mpi_t &mpi); + virtual size_t finish(uint8_t *digest = NULL); + virtual void clone(Hash &dst) const; + + Hash &operator=(const Hash &src); + Hash &operator=(Hash &&src); + + virtual ~Hash(); + + /* Hash algorithm by string representation from cleartext-signed text */ + static pgp_hash_alg_t alg(const char *name); + /* Hash algorithm representation for cleartext-signed text */ + static const char *name(pgp_hash_alg_t alg); + /* Hash algorithm representation for the backend functions */ + static const char *name_backend(pgp_hash_alg_t alg); + /* Size of the hash algorithm output or 0 if algorithm is unknown */ + static size_t size(pgp_hash_alg_t alg); +}; + +#if defined(CRYPTO_BACKEND_BOTAN) +class CRC24 : public Hash { + public: + CRC24(); +}; +#endif +#if defined(CRYPTO_BACKEND_OPENSSL) +class CRC24 { + uint32_t state_; + + public: + CRC24(); + + void add(const void *buf, size_t len); + size_t finish(uint8_t *crc); +}; +#endif -/* @brief Get hash structure for the corresponding algorithm - * - * @param hashes List of pgp_hash_t structures - * @param alg Hash algorithm - * - * @return pointer to the pgp_hash_t structure or NULL if list doesn't contain alg - **/ -const pgp_hash_t *pgp_hash_list_get(std::vector &hashes, pgp_hash_alg_t alg); +class HashList { + std::vector hashes_; -/* - * @brief Update list of hashes with the data - * - * @param hashes List of pgp_hash_t structures - * @param buf buffer with data - * @param len number of bytes in the buffer - **/ -void pgp_hash_list_update(std::vector &hashes, const void *buf, size_t len); + public: + void add_alg(pgp_hash_alg_t alg); + const Hash * get(pgp_hash_alg_t alg) const; + void add(const void *buf, size_t len); + bool empty() const; + std::vector &hashes(); +}; -/* - * @brief Hashes 4 bytes stored as big endian - * - * @param hash Initialized hash ctx - * @param val value to hash - * - * @returns true if operation succeeded, otherwise false - */ -bool pgp_hash_uint32(pgp_hash_t *hash, uint32_t val); +} // namespace rnp #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/hash_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/hash_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include "config.h" +#include "hash.h" +#include "types.h" +#include "utils.h" +#include "str-utils.h" +#include "defaults.h" +#include "sha1cd/hash_sha1cd.h" + +static const id_str_pair openssl_alg_map[] = { + {PGP_HASH_MD5, "md5"}, + {PGP_HASH_SHA1, "sha1"}, + {PGP_HASH_RIPEMD, "ripemd160"}, + {PGP_HASH_SHA256, "sha256"}, + {PGP_HASH_SHA384, "sha384"}, + {PGP_HASH_SHA512, "sha512"}, + {PGP_HASH_SHA224, "sha224"}, + {PGP_HASH_SM3, "sm3"}, + {PGP_HASH_SHA3_256, "sha3-256"}, + {PGP_HASH_SHA3_512, "sha3-512"}, + {0, NULL}, +}; + +namespace rnp { +Hash::Hash(pgp_hash_alg_t alg) +{ + if (alg == PGP_HASH_SHA1) { + handle_ = hash_sha1cd_create(); + if (!handle_) { + throw rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + alg_ = alg; + size_ = rnp::Hash::size(alg); + return; + } + const char *hash_name = rnp::Hash::name_backend(alg); + if (!hash_name) { + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } +#if !defined(ENABLE_SM2) + if (alg == PGP_HASH_SM3) { + RNP_LOG("SM3 hash is not available."); + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } +#endif + const EVP_MD *hash_tp = EVP_get_digestbyname(hash_name); + if (!hash_tp) { + RNP_LOG("Error creating hash object for '%s'", hash_name); + throw rnp_exception(RNP_ERROR_BAD_STATE); + } + EVP_MD_CTX *hash_fn = EVP_MD_CTX_new(); + if (!hash_fn) { + RNP_LOG("Allocation failure"); + throw rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + int res = EVP_DigestInit_ex(hash_fn, hash_tp, NULL); + if (res != 1) { + RNP_LOG("Digest initializataion error %d : %lu", res, ERR_peek_last_error()); + EVP_MD_CTX_free(hash_fn); + throw rnp_exception(RNP_ERROR_BAD_STATE); + } + + alg_ = alg; + size_ = EVP_MD_size(hash_tp); + handle_ = hash_fn; +} + +void +Hash::add(const void *buf, size_t len) +{ + if (!handle_) { + throw rnp_exception(RNP_ERROR_NULL_POINTER); + } + if (alg_ == PGP_HASH_SHA1) { + hash_sha1cd_add(handle_, buf, len); + return; + } + assert(alg_ != PGP_HASH_UNKNOWN); + + EVP_MD_CTX *hash_fn = static_cast(handle_); + int res = EVP_DigestUpdate(hash_fn, buf, len); + if (res != 1) { + RNP_LOG("Digest updating error %d: %lu", res, ERR_peek_last_error()); + throw rnp_exception(RNP_ERROR_GENERIC); + } +} + +size_t +Hash::finish(uint8_t *digest) +{ + if (!handle_) { + return 0; + } + if (alg_ == PGP_HASH_SHA1) { + int res = hash_sha1cd_finish(handle_, digest); + handle_ = NULL; + size_ = 0; + if (res) { + throw rnp_exception(RNP_ERROR_BAD_STATE); + } + return 20; + } + assert(alg_ != PGP_HASH_UNKNOWN); + + EVP_MD_CTX *hash_fn = static_cast(handle_); + int res = digest ? EVP_DigestFinal_ex(hash_fn, digest, NULL) : 1; + EVP_MD_CTX_free(hash_fn); + handle_ = NULL; + if (res != 1) { + RNP_LOG("Digest finalization error %d: %lu", res, ERR_peek_last_error()); + return 0; + } + + size_t outsz = size_; + size_ = 0; + alg_ = PGP_HASH_UNKNOWN; + return outsz; +} + +void +Hash::clone(Hash &dst) const +{ + if (!handle_) { + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + + assert(alg_ != PGP_HASH_UNKNOWN); + + if (dst.handle_) { + dst.finish(); + } + + if (alg_ == PGP_HASH_SHA1) { + dst.handle_ = hash_sha1cd_clone(handle_); + if (!dst.handle_) { + throw rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + dst.size_ = size_; + dst.alg_ = alg_; + return; + } + + EVP_MD_CTX *hash_fn = EVP_MD_CTX_new(); + if (!hash_fn) { + RNP_LOG("Allocation failure"); + throw rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + + int res = EVP_MD_CTX_copy(hash_fn, static_cast(handle_)); + if (res != 1) { + RNP_LOG("Digest copying error %d: %lu", res, ERR_peek_last_error()); + EVP_MD_CTX_free(hash_fn); + throw rnp_exception(RNP_ERROR_BAD_STATE); + } + + dst.size_ = size_; + dst.alg_ = alg_; + dst.handle_ = hash_fn; +} + +Hash::~Hash() +{ + if (!handle_) { + return; + } + if (alg_ == PGP_HASH_SHA1) { + hash_sha1cd_finish(handle_, NULL); + } else { + EVP_MD_CTX_free(static_cast(handle_)); + } +} + +const char * +Hash::name_backend(pgp_hash_alg_t alg) +{ + return id_str_pair::lookup(openssl_alg_map, alg); +} +} // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mem.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mem.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mem.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mem.h 2022-04-15 07:49:22.000000000 +0000 @@ -27,13 +27,75 @@ #ifndef CRYPTO_MEM_H_ #define CRYPTO_MEM_H_ +#include "config.h" #include +#include +#if defined(CRYPTO_BACKEND_BOTAN) #include #include +#elif defined(CRYPTO_BACKEND_OPENSSL) +#include +#endif namespace rnp { +#if defined(CRYPTO_BACKEND_BOTAN) template using secure_vector = Botan::secure_vector; +#elif defined(CRYPTO_BACKEND_OPENSSL) +template class ossl_allocator { + public: + static_assert(std::is_integral::value, "T must be integer type"); + + typedef T value_type; + typedef std::size_t size_type; + + ossl_allocator() noexcept = default; + ossl_allocator(const ossl_allocator &) noexcept = default; + ossl_allocator &operator=(const ossl_allocator &) noexcept = default; + ~ossl_allocator() noexcept = default; + + template ossl_allocator(const ossl_allocator &) noexcept + { + } + + T * + allocate(std::size_t n) + { + if (!n) { + return nullptr; + } + + /* attempt to use OpenSSL secure alloc */ + T *ptr = static_cast(OPENSSL_secure_zalloc(n * sizeof(T))); + if (ptr) { + return ptr; + } + /* fallback to std::alloc if failed */ + ptr = static_cast(std::calloc(n, sizeof(T))); + if (!ptr) + throw std::bad_alloc(); + return ptr; + } + + void + deallocate(T *p, std::size_t n) + { + if (!p) { + return; + } + if (CRYPTO_secure_allocated(p)) { + OPENSSL_secure_clear_free(p, n * sizeof(T)); + return; + } + OPENSSL_cleanse(p, n * sizeof(T)); + std::free(p); + } +}; + +template using secure_vector = std::vector >; +#else +#error Unsupported backend. +#endif template struct secure_array { private: @@ -71,7 +133,13 @@ ~secure_array() { +#if defined(CRYPTO_BACKEND_BOTAN) botan_scrub_mem(&data_[0], sizeof(data_)); +#elif defined(CRYPTO_BACKEND_OPENSSL) + OPENSSL_cleanse(&data_[0], sizeof(data_)); +#else +#error "Unsupported crypto backend." +#endif } }; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mem_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mem_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mem_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mem_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "mem.h" +#include "logging.h" +#include + +void +secure_clear(void *vp, size_t size) +{ + OPENSSL_cleanse(vp, size); +} + +namespace rnp { + +bool +hex_encode(const uint8_t *buf, size_t buf_len, char *hex, size_t hex_len, hex_format_t format) +{ + if (hex_len < (buf_len * 2 + 1)) { + return false; + } + static const char *hex_low = "0123456789abcdef"; + static const char *hex_up = "0123456789ABCDEF"; + const char * hex_ch = (format == HEX_LOWERCASE) ? hex_low : hex_up; + hex[buf_len * 2] = '\0'; + for (size_t i = 0; i < buf_len; i++) { + hex[i << 1] = hex_ch[buf[i] >> 4]; + hex[(i << 1) + 1] = hex_ch[buf[i] & 0xF]; + } + return true; +} + +static bool +hex_char_decode(const char hex, uint8_t &res) +{ + if ((hex >= '0') && (hex <= '9')) { + res = hex - '0'; + return true; + } + if (hex >= 'a' && hex <= 'f') { + res = hex + 10 - 'a'; + return true; + } + if (hex >= 'A' && hex <= 'F') { + res = hex + 10 - 'A'; + return true; + } + return false; +} + +size_t +hex_decode(const char *hex, uint8_t *buf, size_t buf_len) +{ + size_t hexlen = strlen(hex); + + /* check for 0x prefix */ + if ((hexlen >= 2) && (hex[0] == '0') && ((hex[1] == 'x') || (hex[1] == 'X'))) { + hex += 2; + hexlen -= 2; + } + const char *end = hex + hexlen; + uint8_t * buf_st = buf; + uint8_t * buf_en = buf + buf_len; + while (hex < end) { + /* skip whitespaces */ + if ((*hex < '0') && + ((*hex == ' ') || (*hex == '\t') || (*hex == '\r') || (*hex == '\n'))) { + hex++; + continue; + } + if (hexlen < 2) { + RNP_LOG("Invalid hex string length."); + return 0; + } + uint8_t lo, hi; + if (!hex_char_decode(*hex++, hi) || !hex_char_decode(*hex++, lo)) { + RNP_LOG("Hex decode failed on string: %s", hex); + return 0; + } + if (buf == buf_en) { + return 0; + } + *buf++ = (hi << 4) | lo; + } + return buf - buf_st; +} + +} // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mpi.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mpi.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mpi.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mpi.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -31,18 +31,6 @@ #include "mem.h" #include "utils.h" -bignum_t * -mpi2bn(const pgp_mpi_t *val) -{ - return bn_bin2bn(val->mpi, val->len, NULL); -} - -bool -bn2mpi(bignum_t *bn, pgp_mpi_t *val) -{ - return bn_num_bytes(bn, &val->len) && (bn_bn2bin(bn, val->mpi) == 0); -} - size_t mpi_bits(const pgp_mpi_t *val) { @@ -124,32 +112,6 @@ !memcmp(val1->mpi + idx1, val2->mpi + idx2, val1->len - idx1)); } -/* hashes 32-bit length + mpi body (paddded with 0 if high order byte is >= 0x80) */ -bool -mpi_hash(const pgp_mpi_t *val, pgp_hash_t *hash) -{ - size_t len; - size_t idx; - uint8_t padbyte = 0; - bool res = true; - - len = mpi_bytes(val); - for (idx = 0; (idx < len) && (val->mpi[idx] == 0); idx++) - ; - - if (idx >= len) { - return pgp_hash_uint32(hash, 0); - } - - res = pgp_hash_uint32(hash, len - idx); - if (val->mpi[idx] & 0x80) { - res &= pgp_hash_add(hash, &padbyte, 1); - } - res &= pgp_hash_add(hash, val->mpi + idx, len - idx); - - return res; -} - void mpi_forget(pgp_mpi_t *val) { diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mpi.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mpi.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/mpi.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/mpi.h 2022-04-15 07:49:21.000000000 +0000 @@ -27,27 +27,20 @@ #ifndef RNP_MPI_H_ #define RNP_MPI_H_ -#include -#include -#include -#include "bn.h" +#include +#include +#include /* 16384 bits should be pretty enough for now */ #define PGP_MPINT_BITS (16384) #define PGP_MPINT_SIZE (PGP_MPINT_BITS >> 3) -typedef struct pgp_hash_t pgp_hash_t; - /** multi-precision integer, used in signatures and public/secret keys */ typedef struct pgp_mpi_t { uint8_t mpi[PGP_MPINT_SIZE]; size_t len; } pgp_mpi_t; -bignum_t *mpi2bn(const pgp_mpi_t *val); - -bool bn2mpi(bignum_t *bn, pgp_mpi_t *val); - bool mem2mpi(pgp_mpi_t *val, const void *mem, size_t len); void mpi2mem(const pgp_mpi_t *val, void *mem); @@ -58,8 +51,6 @@ size_t mpi_bytes(const pgp_mpi_t *val); -bool mpi_hash(const pgp_mpi_t *val, pgp_hash_t *hash); - bool mpi_equal(const pgp_mpi_t *val1, const pgp_mpi_t *val2); void mpi_forget(pgp_mpi_t *val); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rng.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rng.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rng.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rng.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -1,113 +1,59 @@ /* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). - * Copyright (c) 2009 The NetBSD Foundation, Inc. + * Copyright (c) 2017-2021, [Ribose Inc](https://www.ribose.com). * All rights reserved. * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and - * carried further by Ribose Inc (https://www.ribose.com). + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "rng.h" +#include "types.h" -static inline bool -rng_ensure_initialized(rng_t *ctx) +namespace rnp { +RNG::RNG(Type type) { - assert(ctx); - if (ctx->initialized) { - return true; + if (botan_rng_init(&botan_rng, type == Type::DRBG ? "user" : NULL)) { + throw rnp::rnp_exception(RNP_ERROR_RNG); } - - ctx->initialized = - !botan_rng_init(&ctx->botan_rng, ctx->rng_type == RNG_DRBG ? "user" : NULL); - return ctx->initialized; } -bool -rng_init(rng_t *ctx, rng_type_t rng_type) +RNG::~RNG() { - if (!ctx) { - return false; - } - - if ((rng_type != RNG_DRBG) && (rng_type != RNG_SYSTEM)) { - return false; - } - - ctx->initialized = false; - ctx->rng_type = rng_type; - return (rng_type == RNG_SYSTEM) ? rng_ensure_initialized(ctx) : true; + (void) botan_rng_destroy(botan_rng); } void -rng_destroy(rng_t *ctx) -{ - if (!ctx || !ctx->initialized) { - return; - } - - (void) botan_rng_destroy(ctx->botan_rng); - ctx->botan_rng = NULL; - ctx->initialized = false; -} - -bool -rng_get_data(rng_t *ctx, uint8_t *data, size_t len) +RNG::get(uint8_t *data, size_t len) { - if (!ctx) { - return false; - } - - if (!rng_ensure_initialized(ctx)) { - return false; - } - - if (botan_rng_get(ctx->botan_rng, data, len)) { + if (botan_rng_get(botan_rng, data, len)) { // This should never happen - return false; + throw rnp::rnp_exception(RNP_ERROR_RNG); } - - return true; } struct botan_rng_struct * -rng_handle(rng_t *ctx) +RNG::handle() { - (void) rng_ensure_initialized(ctx); - return ctx->initialized ? ctx->botan_rng : NULL; -} - -bool -rng_generate(uint8_t *data, size_t data_len) -{ - botan_rng_t rng; - if (botan_rng_init(&rng, NULL)) { - return false; - } - const bool rc = botan_rng_get(rng, data, data_len) == 0; - (void) botan_rng_destroy(rng); - return rc; + return botan_rng; } +} // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rng.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rng.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rng.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rng.h 2022-04-15 07:49:22.000000000 +0000 @@ -1,106 +1,78 @@ /* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). - * Copyright (c) 2009 The NetBSD Foundation, Inc. + * Copyright (c) 2017-2021, [Ribose Inc](https://www.ribose.com). * All rights reserved. * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and - * carried further by Ribose Inc (https://www.ribose.com). + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RNP_RANDOM_H_ -#define RNP_RANDOM_H_ +#ifndef RNP_RNG_H_ +#define RNP_RNG_H_ #include #include #include +#include "config.h" -enum { RNG_DRBG, RNG_SYSTEM }; -typedef uint8_t rng_type_t; +#ifdef CRYPTO_BACKEND_BOTAN typedef struct botan_rng_struct *botan_rng_t; +#endif -typedef struct rng_st_t { - bool initialized; - rng_type_t rng_type; - botan_rng_t botan_rng; -} rng_t; +namespace rnp { +class RNG { + private: +#ifdef CRYPTO_BACKEND_BOTAN + struct botan_rng_struct *botan_rng; +#endif + public: + enum Type { DRBG, System }; + /** + * @brief Construct a new RNG object. + * Note: OpenSSL uses own global RNG, so this class is not needed there and left + * only for code-level compatibility. + * + * @param type indicates which random generator to initialize. + * Possible values for Botan backend: + * - DRBG will initialize HMAC_DRBG, this generator is initialized on-demand + * (when used for the first time) + * - SYSTEM will initialize /dev/(u)random + */ + RNG(Type type = Type::DRBG); + ~RNG(); + /** + * @brief Get randoom bytes. + * + * @param data buffer where data should be stored. Cannot be NULL. + * @param len number of bytes required. + */ + void get(uint8_t *data, size_t len); +#ifdef CRYPTO_BACKEND_BOTAN + /** + * @brief Returns internal handle to botan rng. Returned + * handle is always initialized. In case of + * internal error NULL is returned + */ + struct botan_rng_struct *handle(); +#endif +}; +} // namespace rnp -/* - * @brief Initializes rng structure - * - * @param rng_type indicates which random generator to initialize. - * Two values possible - * RNG_DRBG - will initialize HMAC_DRBG, this generator - * is initialized on-demand (when used for the - * first time) - * RNG_SYSTEM will initialize /dev/(u)random - * @returns false if lazy initialization wasn't requested - * and initialization failed, otherwise true - */ -bool rng_init(rng_t *ctx, rng_type_t rng_type); - -/* - * Frees memory allocated by `rng_get_data' - */ -void rng_destroy(rng_t *ctx); - -/* - * @brief Used to retrieve random data. First successful completion - * of this function initializes memory in `ctx' which - * needs to be released with `rng_destroy'. - * - * Function initializes HMAC_DRBG with automatic reseeding - * after each 1024'th call. - * - * @param ctx pointer to rng_t - * @param data [out] output buffer of size at least `len` - * @param len number of bytes to get - * - * @return true on success, false indicates implementation error. - **/ -bool rng_get_data(rng_t *ctx, uint8_t *data, size_t len); - -/* - * @brief Returns internal handle to botan rng. Returned - * handle is always initialized. In case of - * internal error NULL is returned - * - * @param valid pointer to rng_t object - */ -struct botan_rng_struct *rng_handle(rng_t *); - -/* - * @brief Initializes RNG_SYSTEM and generates random data. - * This function should be used only in places where - * rng_t is not available. Using this function may - * impact performance - * - * @param data[out] Output buffer storing random data - * @param data_len length of data to be generated - * - * @return true one success, otherwise false - */ -bool rng_generate(uint8_t *data, size_t data_len); - -#endif // RNP_RANDOM_H_ +#endif // RNP_RNG_H_ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rng_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rng_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rng_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rng_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "rng.h" +#include "types.h" + +namespace rnp { +RNG::RNG(Type type) +{ +} + +RNG::~RNG() +{ +} + +void +RNG::get(uint8_t *data, size_t len) +{ + if (RAND_bytes(data, len) != 1) { + throw rnp::rnp_exception(RNP_ERROR_RNG); + } +} +} // namespace rnp diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rsa.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rsa.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rsa.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rsa.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -82,9 +82,10 @@ #include "hash.h" #include "config.h" #include "utils.h" +#include "bn.h" rnp_result_t -rsa_validate_key(rng_t *rng, const pgp_rsa_key_t *key, bool secret) +rsa_validate_key(rnp::RNG *rng, const pgp_rsa_key_t *key, bool secret) { bignum_t * n = NULL; bignum_t * e = NULL; @@ -105,7 +106,7 @@ goto done; } - if (botan_pubkey_check_key(bpkey, rng_handle(rng), 0)) { + if (botan_pubkey_check_key(bpkey, rng->handle(), 0)) { goto done; } @@ -126,7 +127,7 @@ goto done; } - if (botan_privkey_check_key(bskey, rng_handle(rng), 0)) { + if (botan_privkey_check_key(bskey, rng->handle(), 0)) { goto done; } ret = RNP_SUCCESS; @@ -191,7 +192,7 @@ } rnp_result_t -rsa_encrypt_pkcs1(rng_t * rng, +rsa_encrypt_pkcs1(rnp::RNG * rng, pgp_rsa_encrypted_t *out, const uint8_t * in, size_t in_len, @@ -211,7 +212,7 @@ } out->m.len = sizeof(out->m.mpi); - if (botan_pk_op_encrypt(enc_op, rng_handle(rng), out->m.mpi, &out->m.len, in, in_len)) { + if (botan_pk_op_encrypt(enc_op, rng->handle(), out->m.mpi, &out->m.len, in, in_len)) { out->m.len = 0; goto done; } @@ -242,7 +243,7 @@ snprintf(padding_name, sizeof(padding_name), "EMSA-PKCS1-v1_5(Raw,%s)", - pgp_hash_name_botan(hash_alg)); + rnp::Hash::name_backend(hash_alg)); if (botan_pk_op_verify_create(&verify_op, rsa_key, padding_name, 0) != 0) { goto done; @@ -264,7 +265,7 @@ } rnp_result_t -rsa_sign_pkcs1(rng_t * rng, +rsa_sign_pkcs1(rnp::RNG * rng, pgp_rsa_signature_t *sig, pgp_hash_alg_t hash_alg, const uint8_t * hash, @@ -289,7 +290,7 @@ snprintf(padding_name, sizeof(padding_name), "EMSA-PKCS1-v1_5(Raw,%s)", - pgp_hash_name_botan(hash_alg)); + rnp::Hash::name_backend(hash_alg)); if (botan_pk_op_sign_create(&sign_op, rsa_key, padding_name, 0) != 0) { goto done; @@ -300,7 +301,7 @@ } sig->s.len = sizeof(sig->s.mpi); - if (botan_pk_op_sign_finish(sign_op, rng_handle(rng), sig->s.mpi, &sig->s.len)) { + if (botan_pk_op_sign_finish(sign_op, rng->handle(), sig->s.mpi, &sig->s.len)) { goto done; } @@ -312,7 +313,7 @@ } rnp_result_t -rsa_decrypt_pkcs1(rng_t * rng, +rsa_decrypt_pkcs1(rnp::RNG * rng, uint8_t * out, size_t * out_len, const pgp_rsa_encrypted_t *in, @@ -348,7 +349,7 @@ } rnp_result_t -rsa_generate(rng_t *rng, pgp_rsa_key_t *key, size_t numbits) +rsa_generate(rnp::RNG *rng, pgp_rsa_key_t *key, size_t numbits) { if ((numbits < 1024) || (numbits > PGP_MPINT_BITS)) { return RNP_ERROR_BAD_PARAMETERS; @@ -370,11 +371,11 @@ } if (botan_privkey_create( - &rsa_key, "RSA", std::to_string(numbits).c_str(), rng_handle(rng))) { + &rsa_key, "RSA", std::to_string(numbits).c_str(), rng->handle())) { goto end; } - if (botan_privkey_check_key(rsa_key, rng_handle(rng), 1) != 0) { + if (botan_privkey_check_key(rsa_key, rng->handle(), 1) != 0) { goto end; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rsa.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rsa.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rsa.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rsa.h 2022-04-15 07:49:22.000000000 +0000 @@ -58,17 +58,17 @@ * RSA encrypt/decrypt */ -rnp_result_t rsa_validate_key(rng_t *rng, const pgp_rsa_key_t *key, bool secret); +rnp_result_t rsa_validate_key(rnp::RNG *rng, const pgp_rsa_key_t *key, bool secret); -rnp_result_t rsa_generate(rng_t *rng, pgp_rsa_key_t *key, size_t numbits); +rnp_result_t rsa_generate(rnp::RNG *rng, pgp_rsa_key_t *key, size_t numbits); -rnp_result_t rsa_encrypt_pkcs1(rng_t * rng, +rnp_result_t rsa_encrypt_pkcs1(rnp::RNG * rng, pgp_rsa_encrypted_t *out, const uint8_t * in, size_t in_len, const pgp_rsa_key_t *key); -rnp_result_t rsa_decrypt_pkcs1(rng_t * rng, +rnp_result_t rsa_decrypt_pkcs1(rnp::RNG * rng, uint8_t * out, size_t * out_len, const pgp_rsa_encrypted_t *in, @@ -80,7 +80,7 @@ size_t hash_len, const pgp_rsa_key_t * key); -rnp_result_t rsa_sign_pkcs1(rng_t * rng, +rnp_result_t rsa_sign_pkcs1(rnp::RNG * rng, pgp_rsa_signature_t *sig, pgp_hash_alg_t hash_alg, const uint8_t * hash, diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rsa_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rsa_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/rsa_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/rsa_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "crypto/rsa.h" +#include "hash.h" +#include "config.h" +#include "utils.h" +#include "bn.h" +#include +#include +#include + +static RSA * +rsa_load_public_key(const pgp_rsa_key_t *key) +{ + RSA * rsa = NULL; + bignum_t *n = mpi2bn(&key->n); + bignum_t *e = mpi2bn(&key->e); + + if (!n || !e) { + RNP_LOG("out of memory"); + goto done; + } + rsa = RSA_new(); + if (!rsa) { + RNP_LOG("Out of memory"); + goto done; + } + if (RSA_set0_key(rsa, n, e, NULL) != 1) { + RNP_LOG("Public key load error: %lu", ERR_peek_last_error()); + RSA_free(rsa); + rsa = NULL; + goto done; + } +done: + /* OpenSSL set0 function transfers ownership of bignums */ + if (!rsa) { + bn_free(n); + bn_free(e); + } + return rsa; +} + +static RSA * +rsa_load_secret_key(const pgp_rsa_key_t *key) +{ + RSA * rsa = NULL; + bignum_t *n = mpi2bn(&key->n); + bignum_t *e = mpi2bn(&key->e); + bignum_t *p = mpi2bn(&key->p); + bignum_t *q = mpi2bn(&key->q); + bignum_t *d = mpi2bn(&key->d); + + if (!n || !p || !q || !e || !d) { + RNP_LOG("out of memory"); + goto done; + } + + rsa = RSA_new(); + if (!rsa) { + RNP_LOG("Out of memory"); + goto done; + } + if (RSA_set0_key(rsa, n, e, d) != 1) { + RNP_LOG("Secret key load error: %lu", ERR_peek_last_error()); + RSA_free(rsa); + rsa = NULL; + goto done; + } + /* OpenSSL has p < q, as we do */ + if (RSA_set0_factors(rsa, p, q) != 1) { + RNP_LOG("Factors load error: %lu", ERR_peek_last_error()); + RSA_free(rsa); + rsa = NULL; + goto done; + } +done: + /* OpenSSL set0 function transfers ownership of bignums */ + if (!rsa) { + bn_free(n); + bn_free(p); + bn_free(q); + bn_free(e); + bn_free(d); + } + return rsa; +} + +static EVP_PKEY_CTX * +rsa_init_context(const pgp_rsa_key_t *key, bool secret) +{ + EVP_PKEY *evpkey = EVP_PKEY_new(); + if (!evpkey) { + RNP_LOG("allocation failed"); + return NULL; + } + EVP_PKEY_CTX *ctx = NULL; + RSA * rsakey = secret ? rsa_load_secret_key(key) : rsa_load_public_key(key); + if (!rsakey) { + goto done; + } + if (EVP_PKEY_set1_RSA(evpkey, rsakey) <= 0) { + RNP_LOG("Failed to set key: %lu", ERR_peek_last_error()); + goto done; + } + ctx = EVP_PKEY_CTX_new(evpkey, NULL); + if (!ctx) { + RNP_LOG("Context allocation failed: %lu", ERR_peek_last_error()); + } +done: + RSA_free(rsakey); + EVP_PKEY_free(evpkey); + return ctx; +} + +rnp_result_t +rsa_validate_key(rnp::RNG *rng, const pgp_rsa_key_t *key, bool secret) +{ + if (secret) { + EVP_PKEY_CTX *ctx = rsa_init_context(key, secret); + if (!ctx) { + return RNP_ERROR_GENERIC; + } + int res = EVP_PKEY_check(ctx); + if (res < 0) { + RNP_LOG("Key validation error: %lu", ERR_peek_last_error()); + } + EVP_PKEY_CTX_free(ctx); + return res > 0 ? RNP_SUCCESS : RNP_ERROR_GENERIC; + } + + /* OpenSSL 1.1.1 doesn't have RSA public key check function, so let's do some checks */ + rnp_result_t ret = RNP_ERROR_GENERIC; + bignum_t * n = mpi2bn(&key->n); + bignum_t * e = mpi2bn(&key->e); + if (!n || !e) { + RNP_LOG("out of memory"); + ret = RNP_ERROR_OUT_OF_MEMORY; + goto done; + } + if ((BN_num_bits(n) < 512) || !BN_is_odd(n) || (BN_num_bits(e) < 2) || !BN_is_odd(e)) { + goto done; + } + ret = RNP_SUCCESS; +done: + bn_free(n); + bn_free(e); + return ret; +} + +static bool +rsa_setup_context(EVP_PKEY_CTX *ctx, pgp_hash_alg_t hash_alg = PGP_HASH_UNKNOWN) +{ + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { + RNP_LOG("Failed to set padding: %lu", ERR_peek_last_error()); + return false; + } + if (hash_alg == PGP_HASH_UNKNOWN) { + return true; + } + const char *hash_name = rnp::Hash::name_backend(hash_alg); + if (!hash_name) { + RNP_LOG("Unknown hash: %d", (int) hash_alg); + return false; + } + const EVP_MD *hash_tp = EVP_get_digestbyname(hash_name); + if (!hash_tp) { + RNP_LOG("Error creating hash object for '%s'", hash_name); + return false; + } + if (EVP_PKEY_CTX_set_signature_md(ctx, hash_tp) <= 0) { + RNP_LOG("Failed to set digest: %lu", ERR_peek_last_error()); + return false; + } + return true; +} + +rnp_result_t +rsa_encrypt_pkcs1(rnp::RNG * rng, + pgp_rsa_encrypted_t *out, + const uint8_t * in, + size_t in_len, + const pgp_rsa_key_t *key) +{ + rnp_result_t ret = RNP_ERROR_GENERIC; + EVP_PKEY_CTX *ctx = rsa_init_context(key, false); + if (!ctx) { + return ret; + } + if (EVP_PKEY_encrypt_init(ctx) <= 0) { + RNP_LOG("Failed to initialize encryption: %lu", ERR_peek_last_error()); + goto done; + } + if (!rsa_setup_context(ctx)) { + goto done; + } + out->m.len = sizeof(out->m.mpi); + if (EVP_PKEY_encrypt(ctx, out->m.mpi, &out->m.len, in, in_len) <= 0) { + RNP_LOG("Encryption failed: %lu", ERR_peek_last_error()); + out->m.len = 0; + goto done; + } + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + return ret; +} + +rnp_result_t +rsa_verify_pkcs1(const pgp_rsa_signature_t *sig, + pgp_hash_alg_t hash_alg, + const uint8_t * hash, + size_t hash_len, + const pgp_rsa_key_t * key) +{ + rnp_result_t ret = RNP_ERROR_SIGNATURE_INVALID; + EVP_PKEY_CTX *ctx = rsa_init_context(key, false); + if (!ctx) { + return ret; + } + if (EVP_PKEY_verify_init(ctx) <= 0) { + RNP_LOG("Failed to initialize verification: %lu", ERR_peek_last_error()); + goto done; + } + if (!rsa_setup_context(ctx, hash_alg)) { + goto done; + } + int res; + if (sig->s.len < key->n.len) { + /* OpenSSL doesn't like signatures smaller then N */ + pgp_mpi_t sn; + sn.len = key->n.len; + size_t diff = key->n.len - sig->s.len; + memset(sn.mpi, 0, diff); + memcpy(&sn.mpi[diff], sig->s.mpi, sig->s.len); + res = EVP_PKEY_verify(ctx, sn.mpi, sn.len, hash, hash_len); + } else { + res = EVP_PKEY_verify(ctx, sig->s.mpi, sig->s.len, hash, hash_len); + } + if (res > 0) { + ret = RNP_SUCCESS; + } else { + RNP_LOG("RSA verification failure: %s", + ERR_reason_error_string(ERR_peek_last_error())); + } +done: + EVP_PKEY_CTX_free(ctx); + return ret; +} + +rnp_result_t +rsa_sign_pkcs1(rnp::RNG * rng, + pgp_rsa_signature_t *sig, + pgp_hash_alg_t hash_alg, + const uint8_t * hash, + size_t hash_len, + const pgp_rsa_key_t *key) +{ + rnp_result_t ret = RNP_ERROR_GENERIC; + if (mpi_bytes(&key->q) == 0) { + RNP_LOG("private key not set"); + return ret; + } + EVP_PKEY_CTX *ctx = rsa_init_context(key, true); + if (!ctx) { + return ret; + } + if (EVP_PKEY_sign_init(ctx) <= 0) { + RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); + goto done; + } + if (!rsa_setup_context(ctx, hash_alg)) { + goto done; + } + sig->s.len = PGP_MPINT_SIZE; + if (EVP_PKEY_sign(ctx, sig->s.mpi, &sig->s.len, hash, hash_len) <= 0) { + RNP_LOG("Encryption failed: %lu", ERR_peek_last_error()); + sig->s.len = 0; + goto done; + } + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + return ret; +} + +rnp_result_t +rsa_decrypt_pkcs1(rnp::RNG * rng, + uint8_t * out, + size_t * out_len, + const pgp_rsa_encrypted_t *in, + const pgp_rsa_key_t * key) +{ + rnp_result_t ret = RNP_ERROR_GENERIC; + if (mpi_bytes(&key->q) == 0) { + RNP_LOG("private key not set"); + return ret; + } + EVP_PKEY_CTX *ctx = rsa_init_context(key, true); + if (!ctx) { + return ret; + } + if (EVP_PKEY_decrypt_init(ctx) <= 0) { + RNP_LOG("Failed to initialize encryption: %lu", ERR_peek_last_error()); + goto done; + } + if (!rsa_setup_context(ctx)) { + goto done; + } + *out_len = PGP_MPINT_SIZE; + if (EVP_PKEY_decrypt(ctx, out, out_len, in->m.mpi, in->m.len) <= 0) { + RNP_LOG("Encryption failed: %lu", ERR_peek_last_error()); + *out_len = 0; + goto done; + } + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + return ret; +} + +rnp_result_t +rsa_generate(rnp::RNG *rng, pgp_rsa_key_t *key, size_t numbits) +{ + if ((numbits < 1024) || (numbits > PGP_MPINT_BITS)) { + return RNP_ERROR_BAD_PARAMETERS; + } + + rnp_result_t ret = RNP_ERROR_GENERIC; + RSA * rsa = NULL; + EVP_PKEY * pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + bignum_t * u = NULL; + bignum_t * nq = NULL; + BN_CTX * bnctx = NULL; + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (!ctx) { + RNP_LOG("Failed to create ctx: %lu", ERR_peek_last_error()); + return ret; + } + if (EVP_PKEY_keygen_init(ctx) <= 0) { + RNP_LOG("Failed to init keygen: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, numbits) <= 0) { + RNP_LOG("Failed to set rsa bits: %lu", ERR_peek_last_error()); + goto done; + } + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + RNP_LOG("RSA keygen failed: %lu", ERR_peek_last_error()); + goto done; + } + rsa = EVP_PKEY_get0_RSA(pkey); + if (!rsa) { + RNP_LOG("Failed to retrieve RSA key: %lu", ERR_peek_last_error()); + goto done; + } + if (RSA_check_key(rsa) != 1) { + RNP_LOG("Key validation error: %lu", ERR_peek_last_error()); + goto done; + } + + const bignum_t *n; + const bignum_t *e; + const bignum_t *p; + const bignum_t *q; + const bignum_t *d; + n = RSA_get0_n(rsa); + e = RSA_get0_e(rsa); + d = RSA_get0_d(rsa); + p = RSA_get0_p(rsa); + q = RSA_get0_q(rsa); + if (!n || !e || !d || !p || !q) { + ret = RNP_ERROR_OUT_OF_MEMORY; + goto done; + } + /* OpenSSL doesn't care whether p < q */ + if (BN_cmp(p, q) > 0) { + const bignum_t *tmp = p; + p = q; + q = tmp; + } + /* we need to calculate u, since we need inverse of p mod q, while OpenSSL has inverse of q + * mod p, and doesn't care of p < q */ + bnctx = BN_CTX_new(); + u = BN_new(); + nq = BN_new(); + if (!ctx || !u || !nq) { + ret = RNP_ERROR_OUT_OF_MEMORY; + goto done; + } + BN_with_flags(nq, q, BN_FLG_CONSTTIME); + /* calculate inverse of p mod q */ + if (!BN_mod_inverse(u, p, nq, bnctx)) { + bn_free(nq); + RNP_LOG("Failed to calculate u"); + ret = RNP_ERROR_BAD_STATE; + goto done; + } + bn_free(nq); + bn2mpi(n, &key->n); + bn2mpi(e, &key->e); + bn2mpi(p, &key->p); + bn2mpi(q, &key->q); + bn2mpi(d, &key->d); + bn2mpi(u, &key->u); + ret = RNP_SUCCESS; +done: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + BN_CTX_free(bnctx); + bn_free(u); + return ret; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/s2k.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/s2k.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/s2k.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/s2k.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -28,7 +28,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include "config.h" #ifndef _MSC_VER @@ -42,6 +41,9 @@ #include "rnp.h" #include "types.h" #include "utils.h" +#ifdef CRYPTO_BACKEND_BOTAN +#include +#endif bool pgp_s2k_derive_key(pgp_s2k_t *s2k, const char *password, uint8_t *key, int keysize) @@ -75,6 +77,7 @@ return true; } +#ifdef CRYPTO_BACKEND_BOTAN int pgp_s2k_iterated(pgp_hash_alg_t alg, uint8_t * out, @@ -84,7 +87,8 @@ size_t iterations) { char s2k_algo_str[128]; - snprintf(s2k_algo_str, sizeof(s2k_algo_str), "OpenPGP-S2K(%s)", pgp_hash_name_botan(alg)); + snprintf( + s2k_algo_str, sizeof(s2k_algo_str), "OpenPGP-S2K(%s)", rnp::Hash::name_backend(alg)); return botan_pwdhash(s2k_algo_str, iterations, @@ -97,6 +101,7 @@ salt, salt ? PGP_SALT_SIZE : 0); } +#endif size_t pgp_s2k_decode_iterations(uint8_t c) @@ -157,24 +162,23 @@ trial_msec = DEFAULT_S2K_TUNE_MSEC; } - pgp_hash_t hash = {}; - if (!pgp_hash_create(&hash, alg)) { - RNP_LOG("failed to create hash object"); - return 0; - } - uint64_t start = get_timestamp_usec(); uint64_t end = start; - uint8_t buf[8192] = {0}; size_t bytes = 0; - while (end - start < trial_msec * 1000ull) { - pgp_hash_add(&hash, buf, sizeof(buf)); - bytes += sizeof(buf); - end = get_timestamp_usec(); + try { + rnp::Hash hash(alg); + uint8_t buf[8192] = {0}; + while (end - start < trial_msec * 1000ull) { + hash.add(buf, sizeof(buf)); + bytes += sizeof(buf); + end = get_timestamp_usec(); + } + hash.finish(buf); + } catch (const std::exception &e) { + RNP_LOG("Failed to hash data: %s", e.what()); + return 0; } - pgp_hash_finish(&hash, buf); - uint64_t duration = end - start; const uint8_t MIN_ITERS = 96; if (duration == 0) { @@ -186,13 +190,5 @@ const double bytes_for_target = bytes_per_usec * desired_usec; const uint8_t iters = pgp_s2k_encode_iterations(bytes_for_target); - RNP_DLOG( - "PGP S2K hash %d tuned bytes/usec=%f desired_usec=%f bytes_for_target=%f iters %d", - alg, - bytes_per_usec, - desired_usec, - bytes_for_target, - iters); - return pgp_s2k_decode_iterations((iters > MIN_ITERS) ? iters : MIN_ITERS); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/s2k.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/s2k.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/s2k.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/s2k.h 2022-04-15 07:49:22.000000000 +0000 @@ -31,6 +31,7 @@ #ifndef RNP_S2K_H_ #define RNP_S2K_H_ +#include #include "hash.h" typedef struct pgp_s2k_t pgp_s2k_t; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/s2k_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/s2k_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/s2k_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/s2k_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "s2k.h" +#include "mem.h" +#include "logging.h" + +int +pgp_s2k_iterated(pgp_hash_alg_t alg, + uint8_t * out, + size_t output_len, + const char * password, + const uint8_t *salt, + size_t iterations) +{ + if ((iterations > 1) && !salt) { + RNP_LOG("Iterated S2K mus be salted as well."); + return 1; + } + size_t hash_len = rnp::Hash::size(alg); + if (!hash_len) { + RNP_LOG("Unknown digest: %d", (int) alg); + return 1; + } + try { + size_t pswd_len = strlen(password); + size_t salt_len = salt ? PGP_SALT_SIZE : 0; + + rnp::secure_vector data(salt_len + pswd_len); + if (salt_len) { + memcpy(data.data(), salt, PGP_SALT_SIZE); + } + memcpy(data.data() + salt_len, password, pswd_len); + size_t zeroes = 0; + + while (output_len) { + /* create hash context */ + rnp::Hash hash(alg); + /* add leading zeroes */ + for (size_t z = 0; z < zeroes; z++) { + uint8_t zero = 0; + hash.add(&zero, 1); + } + if (!data.empty()) { + /* if iteration is 1 then still hash the whole data chunk */ + size_t left = std::max(data.size(), iterations); + while (left) { + size_t to_hash = std::min(left, data.size()); + hash.add(data.data(), to_hash); + left -= to_hash; + } + } + rnp::secure_vector dgst(hash_len); + size_t out_cpy = std::min(dgst.size(), output_len); + if (hash.finish(dgst.data()) != dgst.size()) { + RNP_LOG("Unexpected digest size."); + return 1; + } + memcpy(out, dgst.data(), out_cpy); + output_len -= out_cpy; + out += out_cpy; + zeroes++; + } + return 0; + } catch (const std::exception &e) { + RNP_LOG("s2k failed: %s", e.what()); + return 1; + } +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "hash_sha1cd.h" +#include "sha1.h" +#include "logging.h" + +void * +hash_sha1cd_create() +{ + SHA1_CTX *res = (SHA1_CTX *) calloc(1, sizeof(SHA1_CTX)); + if (res) { + SHA1DCInit(res); + } + return res; +} + +/* This produces runtime error: load of misaligned address 0x60d0000030a9 for type 'const + * uint32_t' (aka 'const unsigned int'), which requires 4 byte alignment */ +#if defined(__clang__) +__attribute__((no_sanitize("undefined"))) +#endif +void +hash_sha1cd_add(void *ctx, const void *buf, size_t len) +{ + SHA1DCUpdate((SHA1_CTX *) ctx, (const char *) buf, len); +} + +void * +hash_sha1cd_clone(void *ctx) +{ + SHA1_CTX *res = (SHA1_CTX *) calloc(1, sizeof(SHA1_CTX)); + if (res) { + *res = *((SHA1_CTX *) ctx); + } + return res; +} + +#if defined(__clang__) +__attribute__((no_sanitize("undefined"))) +#endif +int +hash_sha1cd_finish(void *ctx, uint8_t *digest) +{ + unsigned char fixed_digest[20]; + int res = 0; + if ((res = SHA1DCFinal(fixed_digest, (SHA1_CTX *) ctx)) && digest) { + /* Show warning only if digest is non-null */ + RNP_LOG("Warning! SHA1 collision detected and mitigated."); + } + if (digest) { + memcpy(digest, fixed_digest, 20); + } + free(ctx); + return res; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/hash_sha1cd.h 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CRYPTO_HASH_SHA1CD_H_ +#define CRYPTO_HASH_SHA1CD_H_ +#include + +void *hash_sha1cd_create(); + +void hash_sha1cd_add(void *ctx, const void *buf, size_t len); + +void *hash_sha1cd_clone(void *ctx); + +int hash_sha1cd_finish(void *ctx, uint8_t *digest); + +#endif \ No newline at end of file diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.c thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.c --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.c 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.c 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,2162 @@ +/*** + * Copyright 2017 Marc Stevens , Dan Shumow (danshu@microsoft.com) + * Distributed under the MIT Software License. + * See accompanying file LICENSE.txt or copy at + * https://opensource.org/licenses/MIT + ***/ + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#include +#include +#include +#ifdef __unix__ +#include /* make sure macros like _BIG_ENDIAN visible */ +#endif +#endif + +#ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C +#include SHA1DC_CUSTOM_INCLUDE_SHA1_C +#endif + +#ifndef SHA1DC_INIT_SAFE_HASH_DEFAULT +#define SHA1DC_INIT_SAFE_HASH_DEFAULT 1 +#endif + +#include "sha1.h" +#include "ubc_check.h" + +#if (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \ + defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \ + defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \ + defined(__386) || defined(_M_X64) || defined(_M_AMD64)) +#define SHA1DC_ON_INTEL_LIKE_PROCESSOR +#endif + +/* + Because Little-Endian architectures are most common, + we only set SHA1DC_BIGENDIAN if one of these conditions is met. + Note that all MSFT platforms are little endian, + so none of these will be defined under the MSC compiler. + If you are compiling on a big endian platform and your compiler does not define one of + these, you will have to add whatever macros your tool chain defines to indicate + Big-Endianness. + */ + +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) +/* + * Should detect Big Endian under GCC since at least 4.6.0 (gcc svn + * rev #165881). See + * https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html + * + * This also works under clang since 3.2, it copied the GCC-ism. See + * clang.git's 3b198a97d2 ("Preprocessor: add __BYTE_ORDER__ + * predefined macro", 2012-07-27) + */ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define SHA1DC_BIGENDIAN +#endif + +/* Not under GCC-alike */ +#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) +/* + * Should detect Big Endian under glibc.git since 14245eb70e ("entered + * into RCS", 1992-11-25). Defined in which will have been + * brought in by standard headers. See glibc.git and + * https://sourceforge.net/p/predef/wiki/Endianness/ + */ +#if __BYTE_ORDER == __BIG_ENDIAN +#define SHA1DC_BIGENDIAN +#endif + +/* Not under GCC-alike or glibc */ +#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) +/* + * *BSD and newlib (embedded linux, cygwin, etc). + * the defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) part prevents + * this condition from matching with Solaris/sparc. + * (Solaris defines only one endian macro) + */ +#if _BYTE_ORDER == _BIG_ENDIAN +#define SHA1DC_BIGENDIAN +#endif + +/* Not under GCC-alike or glibc or *BSD or newlib */ +#elif (defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ + defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(__sparc)) +/* + * Should define Big Endian for a whitelist of known processors. See + * https://sourceforge.net/p/predef/wiki/Endianness/ and + * http://www.oracle.com/technetwork/server-storage/solaris/portingtosolaris-138514.html + */ +#define SHA1DC_BIGENDIAN + +/* Not under GCC-alike or glibc or *BSD or newlib or */ +#elif (defined(_AIX) || defined(__hpux)) + +/* + * Defines Big Endian on a whitelist of OSs that are known to be Big + * Endian-only. See + * https://public-inbox.org/git/93056823-2740-d072-1ebd-46b440b33d7e@felt.demon.nl/ + */ +#define SHA1DC_BIGENDIAN + +/* Not under GCC-alike or glibc or *BSD or newlib or or */ +#elif defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR) +/* + * As a last resort before we do anything else we're not 100% sure + * about below, we blacklist specific processors here. We could add + * more, see e.g. https://wiki.debian.org/ArchitectureSpecificsMemo + */ +#else /* Not under GCC-alike or glibc or *BSD or newlib or or or */ + +/* We do nothing more here for now */ +/*#error "Uncomment this to see if you fall through all the detection"*/ + +#endif /* Big Endian detection */ + +#if (defined(SHA1DC_FORCE_LITTLEENDIAN) && defined(SHA1DC_BIGENDIAN)) +#undef SHA1DC_BIGENDIAN +#endif +#if (defined(SHA1DC_FORCE_BIGENDIAN) && !defined(SHA1DC_BIGENDIAN)) +#define SHA1DC_BIGENDIAN +#endif +/*ENDIANNESS SELECTION*/ + +#ifndef SHA1DC_FORCE_ALIGNED_ACCESS +#if defined(SHA1DC_FORCE_UNALIGNED_ACCESS) || defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR) +#define SHA1DC_ALLOW_UNALIGNED_ACCESS +#endif /*UNALIGNED ACCESS DETECTION*/ +#endif /*FORCE ALIGNED ACCESS*/ + +#define rotate_right(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) +#define rotate_left(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +#define sha1_bswap32(x) \ + { \ + x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); \ + x = (x << 16) | (x >> 16); \ + } + +#define sha1_mix(W, t) (rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1)) + +#ifdef SHA1DC_BIGENDIAN +#define sha1_load(m, t, temp) \ + { \ + temp = m[t]; \ + } +#else +#define sha1_load(m, t, temp) \ + { \ + temp = m[t]; \ + sha1_bswap32(temp); \ + } +#endif + +#define sha1_store(W, t, x) *(volatile uint32_t *) &W[t] = x + +#define sha1_f1(b, c, d) ((d) ^ ((b) & ((c) ^ (d)))) +#define sha1_f2(b, c, d) ((b) ^ (c) ^ (d)) +#define sha1_f3(b, c, d) (((b) & (c)) + ((d) & ((b) ^ (c)))) +#define sha1_f4(b, c, d) ((b) ^ (c) ^ (d)) + +#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, m, t) \ + { \ + e += rotate_left(a, 5) + sha1_f1(b, c, d) + 0x5A827999 + m[t]; \ + b = rotate_left(b, 30); \ + } +#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, m, t) \ + { \ + e += rotate_left(a, 5) + sha1_f2(b, c, d) + 0x6ED9EBA1 + m[t]; \ + b = rotate_left(b, 30); \ + } +#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, m, t) \ + { \ + e += rotate_left(a, 5) + sha1_f3(b, c, d) + 0x8F1BBCDC + m[t]; \ + b = rotate_left(b, 30); \ + } +#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, m, t) \ + { \ + e += rotate_left(a, 5) + sha1_f4(b, c, d) + 0xCA62C1D6 + m[t]; \ + b = rotate_left(b, 30); \ + } + +#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, m, t) \ + { \ + b = rotate_right(b, 30); \ + e -= rotate_left(a, 5) + sha1_f1(b, c, d) + 0x5A827999 + m[t]; \ + } +#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, m, t) \ + { \ + b = rotate_right(b, 30); \ + e -= rotate_left(a, 5) + sha1_f2(b, c, d) + 0x6ED9EBA1 + m[t]; \ + } +#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, m, t) \ + { \ + b = rotate_right(b, 30); \ + e -= rotate_left(a, 5) + sha1_f3(b, c, d) + 0x8F1BBCDC + m[t]; \ + } +#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, m, t) \ + { \ + b = rotate_right(b, 30); \ + e -= rotate_left(a, 5) + sha1_f4(b, c, d) + 0xCA62C1D6 + m[t]; \ + } + +#define SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, t, temp) \ + { \ + sha1_load(m, t, temp); \ + sha1_store(W, t, temp); \ + e += temp + rotate_left(a, 5) + sha1_f1(b, c, d) + 0x5A827999; \ + b = rotate_left(b, 30); \ + } + +#define SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(a, b, c, d, e, W, t, temp) \ + { \ + temp = sha1_mix(W, t); \ + sha1_store(W, t, temp); \ + e += temp + rotate_left(a, 5) + sha1_f1(b, c, d) + 0x5A827999; \ + b = rotate_left(b, 30); \ + } + +#define SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, t, temp) \ + { \ + temp = sha1_mix(W, t); \ + sha1_store(W, t, temp); \ + e += temp + rotate_left(a, 5) + sha1_f2(b, c, d) + 0x6ED9EBA1; \ + b = rotate_left(b, 30); \ + } + +#define SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, t, temp) \ + { \ + temp = sha1_mix(W, t); \ + sha1_store(W, t, temp); \ + e += temp + rotate_left(a, 5) + sha1_f3(b, c, d) + 0x8F1BBCDC; \ + b = rotate_left(b, 30); \ + } + +#define SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, t, temp) \ + { \ + temp = sha1_mix(W, t); \ + sha1_store(W, t, temp); \ + e += temp + rotate_left(a, 5) + sha1_f4(b, c, d) + 0xCA62C1D6; \ + b = rotate_left(b, 30); \ + } + +#define SHA1_STORE_STATE(i) \ + states[i][0] = a; \ + states[i][1] = b; \ + states[i][2] = c; \ + states[i][3] = d; \ + states[i][4] = e; + +#ifdef BUILDNOCOLLDETECTSHA1COMPRESSION +void +sha1_compression(uint32_t ihv[5], const uint32_t m[16]) +{ + uint32_t W[80]; + uint32_t a, b, c, d, e; + unsigned i; + + memcpy(W, m, 16 * 4); + for (i = 16; i < 80; ++i) + W[i] = sha1_mix(W, i); + + a = ihv[0]; + b = ihv[1]; + c = ihv[2]; + d = ihv[3]; + e = ihv[4]; + + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); + + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); + + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); + + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); + + ihv[0] += a; + ihv[1] += b; + ihv[2] += c; + ihv[3] += d; + ihv[4] += e; +} +#endif /*BUILDNOCOLLDETECTSHA1COMPRESSION*/ + +static void +sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]) +{ + uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; + + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); + + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); + + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); + + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); + + ihv[0] += a; + ihv[1] += b; + ihv[2] += c; + ihv[3] += d; + ihv[4] += e; +} + +void +sha1_compression_states(uint32_t ihv[5], + const uint32_t m[16], + uint32_t W[80], + uint32_t states[80][5]) +{ + uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; + uint32_t temp; + +#ifdef DOSTORESTATE00 + SHA1_STORE_STATE(0) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 0, temp); + +#ifdef DOSTORESTATE01 + SHA1_STORE_STATE(1) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 1, temp); + +#ifdef DOSTORESTATE02 + SHA1_STORE_STATE(2) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 2, temp); + +#ifdef DOSTORESTATE03 + SHA1_STORE_STATE(3) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 3, temp); + +#ifdef DOSTORESTATE04 + SHA1_STORE_STATE(4) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 4, temp); + +#ifdef DOSTORESTATE05 + SHA1_STORE_STATE(5) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 5, temp); + +#ifdef DOSTORESTATE06 + SHA1_STORE_STATE(6) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 6, temp); + +#ifdef DOSTORESTATE07 + SHA1_STORE_STATE(7) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 7, temp); + +#ifdef DOSTORESTATE08 + SHA1_STORE_STATE(8) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 8, temp); + +#ifdef DOSTORESTATE09 + SHA1_STORE_STATE(9) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 9, temp); + +#ifdef DOSTORESTATE10 + SHA1_STORE_STATE(10) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 10, temp); + +#ifdef DOSTORESTATE11 + SHA1_STORE_STATE(11) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 11, temp); + +#ifdef DOSTORESTATE12 + SHA1_STORE_STATE(12) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 12, temp); + +#ifdef DOSTORESTATE13 + SHA1_STORE_STATE(13) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 13, temp); + +#ifdef DOSTORESTATE14 + SHA1_STORE_STATE(14) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 14, temp); + +#ifdef DOSTORESTATE15 + SHA1_STORE_STATE(15) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 15, temp); + +#ifdef DOSTORESTATE16 + SHA1_STORE_STATE(16) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(e, a, b, c, d, W, 16, temp); + +#ifdef DOSTORESTATE17 + SHA1_STORE_STATE(17) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(d, e, a, b, c, W, 17, temp); + +#ifdef DOSTORESTATE18 + SHA1_STORE_STATE(18) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(c, d, e, a, b, W, 18, temp); + +#ifdef DOSTORESTATE19 + SHA1_STORE_STATE(19) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(b, c, d, e, a, W, 19, temp); + +#ifdef DOSTORESTATE20 + SHA1_STORE_STATE(20) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 20, temp); + +#ifdef DOSTORESTATE21 + SHA1_STORE_STATE(21) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 21, temp); + +#ifdef DOSTORESTATE22 + SHA1_STORE_STATE(22) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 22, temp); + +#ifdef DOSTORESTATE23 + SHA1_STORE_STATE(23) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 23, temp); + +#ifdef DOSTORESTATE24 + SHA1_STORE_STATE(24) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 24, temp); + +#ifdef DOSTORESTATE25 + SHA1_STORE_STATE(25) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 25, temp); + +#ifdef DOSTORESTATE26 + SHA1_STORE_STATE(26) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 26, temp); + +#ifdef DOSTORESTATE27 + SHA1_STORE_STATE(27) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 27, temp); + +#ifdef DOSTORESTATE28 + SHA1_STORE_STATE(28) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 28, temp); + +#ifdef DOSTORESTATE29 + SHA1_STORE_STATE(29) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 29, temp); + +#ifdef DOSTORESTATE30 + SHA1_STORE_STATE(30) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 30, temp); + +#ifdef DOSTORESTATE31 + SHA1_STORE_STATE(31) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 31, temp); + +#ifdef DOSTORESTATE32 + SHA1_STORE_STATE(32) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 32, temp); + +#ifdef DOSTORESTATE33 + SHA1_STORE_STATE(33) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 33, temp); + +#ifdef DOSTORESTATE34 + SHA1_STORE_STATE(34) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 34, temp); + +#ifdef DOSTORESTATE35 + SHA1_STORE_STATE(35) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 35, temp); + +#ifdef DOSTORESTATE36 + SHA1_STORE_STATE(36) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 36, temp); + +#ifdef DOSTORESTATE37 + SHA1_STORE_STATE(37) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 37, temp); + +#ifdef DOSTORESTATE38 + SHA1_STORE_STATE(38) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 38, temp); + +#ifdef DOSTORESTATE39 + SHA1_STORE_STATE(39) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 39, temp); + +#ifdef DOSTORESTATE40 + SHA1_STORE_STATE(40) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 40, temp); + +#ifdef DOSTORESTATE41 + SHA1_STORE_STATE(41) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 41, temp); + +#ifdef DOSTORESTATE42 + SHA1_STORE_STATE(42) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 42, temp); + +#ifdef DOSTORESTATE43 + SHA1_STORE_STATE(43) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 43, temp); + +#ifdef DOSTORESTATE44 + SHA1_STORE_STATE(44) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 44, temp); + +#ifdef DOSTORESTATE45 + SHA1_STORE_STATE(45) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 45, temp); + +#ifdef DOSTORESTATE46 + SHA1_STORE_STATE(46) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 46, temp); + +#ifdef DOSTORESTATE47 + SHA1_STORE_STATE(47) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 47, temp); + +#ifdef DOSTORESTATE48 + SHA1_STORE_STATE(48) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 48, temp); + +#ifdef DOSTORESTATE49 + SHA1_STORE_STATE(49) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 49, temp); + +#ifdef DOSTORESTATE50 + SHA1_STORE_STATE(50) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 50, temp); + +#ifdef DOSTORESTATE51 + SHA1_STORE_STATE(51) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 51, temp); + +#ifdef DOSTORESTATE52 + SHA1_STORE_STATE(52) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 52, temp); + +#ifdef DOSTORESTATE53 + SHA1_STORE_STATE(53) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 53, temp); + +#ifdef DOSTORESTATE54 + SHA1_STORE_STATE(54) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 54, temp); + +#ifdef DOSTORESTATE55 + SHA1_STORE_STATE(55) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 55, temp); + +#ifdef DOSTORESTATE56 + SHA1_STORE_STATE(56) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 56, temp); + +#ifdef DOSTORESTATE57 + SHA1_STORE_STATE(57) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 57, temp); + +#ifdef DOSTORESTATE58 + SHA1_STORE_STATE(58) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 58, temp); + +#ifdef DOSTORESTATE59 + SHA1_STORE_STATE(59) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 59, temp); + +#ifdef DOSTORESTATE60 + SHA1_STORE_STATE(60) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 60, temp); + +#ifdef DOSTORESTATE61 + SHA1_STORE_STATE(61) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 61, temp); + +#ifdef DOSTORESTATE62 + SHA1_STORE_STATE(62) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 62, temp); + +#ifdef DOSTORESTATE63 + SHA1_STORE_STATE(63) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 63, temp); + +#ifdef DOSTORESTATE64 + SHA1_STORE_STATE(64) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 64, temp); + +#ifdef DOSTORESTATE65 + SHA1_STORE_STATE(65) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 65, temp); + +#ifdef DOSTORESTATE66 + SHA1_STORE_STATE(66) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 66, temp); + +#ifdef DOSTORESTATE67 + SHA1_STORE_STATE(67) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 67, temp); + +#ifdef DOSTORESTATE68 + SHA1_STORE_STATE(68) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 68, temp); + +#ifdef DOSTORESTATE69 + SHA1_STORE_STATE(69) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 69, temp); + +#ifdef DOSTORESTATE70 + SHA1_STORE_STATE(70) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 70, temp); + +#ifdef DOSTORESTATE71 + SHA1_STORE_STATE(71) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 71, temp); + +#ifdef DOSTORESTATE72 + SHA1_STORE_STATE(72) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 72, temp); + +#ifdef DOSTORESTATE73 + SHA1_STORE_STATE(73) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 73, temp); + +#ifdef DOSTORESTATE74 + SHA1_STORE_STATE(74) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 74, temp); + +#ifdef DOSTORESTATE75 + SHA1_STORE_STATE(75) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 75, temp); + +#ifdef DOSTORESTATE76 + SHA1_STORE_STATE(76) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 76, temp); + +#ifdef DOSTORESTATE77 + SHA1_STORE_STATE(77) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 77, temp); + +#ifdef DOSTORESTATE78 + SHA1_STORE_STATE(78) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 78, temp); + +#ifdef DOSTORESTATE79 + SHA1_STORE_STATE(79) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 79, temp); + + ihv[0] += a; + ihv[1] += b; + ihv[2] += c; + ihv[3] += d; + ihv[4] += e; +} + +#define SHA1_RECOMPRESS(t) \ + static void sha1recompress_fast_##t( \ + uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \ + { \ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; \ + if (t > 79) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 79); \ + if (t > 78) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 78); \ + if (t > 77) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 77); \ + if (t > 76) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 76); \ + if (t > 75) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 75); \ + if (t > 74) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 74); \ + if (t > 73) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 73); \ + if (t > 72) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 72); \ + if (t > 71) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 71); \ + if (t > 70) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 70); \ + if (t > 69) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 69); \ + if (t > 68) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 68); \ + if (t > 67) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 67); \ + if (t > 66) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 66); \ + if (t > 65) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 65); \ + if (t > 64) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 64); \ + if (t > 63) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 63); \ + if (t > 62) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 62); \ + if (t > 61) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 61); \ + if (t > 60) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 60); \ + if (t > 59) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 59); \ + if (t > 58) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 58); \ + if (t > 57) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 57); \ + if (t > 56) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 56); \ + if (t > 55) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 55); \ + if (t > 54) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 54); \ + if (t > 53) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 53); \ + if (t > 52) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 52); \ + if (t > 51) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 51); \ + if (t > 50) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 50); \ + if (t > 49) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 49); \ + if (t > 48) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 48); \ + if (t > 47) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 47); \ + if (t > 46) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 46); \ + if (t > 45) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 45); \ + if (t > 44) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 44); \ + if (t > 43) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 43); \ + if (t > 42) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 42); \ + if (t > 41) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 41); \ + if (t > 40) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 40); \ + if (t > 39) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 39); \ + if (t > 38) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 38); \ + if (t > 37) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 37); \ + if (t > 36) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 36); \ + if (t > 35) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 35); \ + if (t > 34) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 34); \ + if (t > 33) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 33); \ + if (t > 32) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 32); \ + if (t > 31) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 31); \ + if (t > 30) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 30); \ + if (t > 29) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 29); \ + if (t > 28) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 28); \ + if (t > 27) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 27); \ + if (t > 26) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 26); \ + if (t > 25) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 25); \ + if (t > 24) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 24); \ + if (t > 23) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 23); \ + if (t > 22) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 22); \ + if (t > 21) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 21); \ + if (t > 20) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 20); \ + if (t > 19) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 19); \ + if (t > 18) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 18); \ + if (t > 17) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 17); \ + if (t > 16) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 16); \ + if (t > 15) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 15); \ + if (t > 14) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 14); \ + if (t > 13) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 13); \ + if (t > 12) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 12); \ + if (t > 11) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 11); \ + if (t > 10) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 10); \ + if (t > 9) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 9); \ + if (t > 8) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 8); \ + if (t > 7) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 7); \ + if (t > 6) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 6); \ + if (t > 5) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 5); \ + if (t > 4) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 4); \ + if (t > 3) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 3); \ + if (t > 2) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 2); \ + if (t > 1) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 1); \ + if (t > 0) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 0); \ + ihvin[0] = a; \ + ihvin[1] = b; \ + ihvin[2] = c; \ + ihvin[3] = d; \ + ihvin[4] = e; \ + a = state[0]; \ + b = state[1]; \ + c = state[2]; \ + d = state[3]; \ + e = state[4]; \ + if (t <= 0) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 0); \ + if (t <= 1) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 1); \ + if (t <= 2) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 2); \ + if (t <= 3) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 3); \ + if (t <= 4) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 4); \ + if (t <= 5) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 5); \ + if (t <= 6) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 6); \ + if (t <= 7) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 7); \ + if (t <= 8) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 8); \ + if (t <= 9) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 9); \ + if (t <= 10) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 10); \ + if (t <= 11) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 11); \ + if (t <= 12) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 12); \ + if (t <= 13) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 13); \ + if (t <= 14) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 14); \ + if (t <= 15) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 15); \ + if (t <= 16) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 16); \ + if (t <= 17) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 17); \ + if (t <= 18) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 18); \ + if (t <= 19) \ + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 19); \ + if (t <= 20) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 20); \ + if (t <= 21) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 21); \ + if (t <= 22) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 22); \ + if (t <= 23) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 23); \ + if (t <= 24) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 24); \ + if (t <= 25) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 25); \ + if (t <= 26) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 26); \ + if (t <= 27) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 27); \ + if (t <= 28) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 28); \ + if (t <= 29) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 29); \ + if (t <= 30) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 30); \ + if (t <= 31) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 31); \ + if (t <= 32) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 32); \ + if (t <= 33) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 33); \ + if (t <= 34) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 34); \ + if (t <= 35) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 35); \ + if (t <= 36) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 36); \ + if (t <= 37) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 37); \ + if (t <= 38) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 38); \ + if (t <= 39) \ + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 39); \ + if (t <= 40) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 40); \ + if (t <= 41) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 41); \ + if (t <= 42) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 42); \ + if (t <= 43) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 43); \ + if (t <= 44) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 44); \ + if (t <= 45) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 45); \ + if (t <= 46) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 46); \ + if (t <= 47) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 47); \ + if (t <= 48) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 48); \ + if (t <= 49) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 49); \ + if (t <= 50) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 50); \ + if (t <= 51) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 51); \ + if (t <= 52) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 52); \ + if (t <= 53) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 53); \ + if (t <= 54) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 54); \ + if (t <= 55) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 55); \ + if (t <= 56) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 56); \ + if (t <= 57) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 57); \ + if (t <= 58) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 58); \ + if (t <= 59) \ + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 59); \ + if (t <= 60) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 60); \ + if (t <= 61) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 61); \ + if (t <= 62) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 62); \ + if (t <= 63) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 63); \ + if (t <= 64) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 64); \ + if (t <= 65) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 65); \ + if (t <= 66) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 66); \ + if (t <= 67) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 67); \ + if (t <= 68) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 68); \ + if (t <= 69) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 69); \ + if (t <= 70) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 70); \ + if (t <= 71) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 71); \ + if (t <= 72) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 72); \ + if (t <= 73) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 73); \ + if (t <= 74) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 74); \ + if (t <= 75) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 75); \ + if (t <= 76) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 76); \ + if (t <= 77) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 77); \ + if (t <= 78) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 78); \ + if (t <= 79) \ + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 79); \ + ihvout[0] = ihvin[0] + a; \ + ihvout[1] = ihvin[1] + b; \ + ihvout[2] = ihvin[2] + c; \ + ihvout[3] = ihvin[3] + d; \ + ihvout[4] = ihvin[4] + e; \ + } + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4127) /* Compiler complains about the checks in the above macro \ + being constant. */ +#endif + +#ifdef DOSTORESTATE0 +SHA1_RECOMPRESS(0) +#endif + +#ifdef DOSTORESTATE1 +SHA1_RECOMPRESS(1) +#endif + +#ifdef DOSTORESTATE2 +SHA1_RECOMPRESS(2) +#endif + +#ifdef DOSTORESTATE3 +SHA1_RECOMPRESS(3) +#endif + +#ifdef DOSTORESTATE4 +SHA1_RECOMPRESS(4) +#endif + +#ifdef DOSTORESTATE5 +SHA1_RECOMPRESS(5) +#endif + +#ifdef DOSTORESTATE6 +SHA1_RECOMPRESS(6) +#endif + +#ifdef DOSTORESTATE7 +SHA1_RECOMPRESS(7) +#endif + +#ifdef DOSTORESTATE8 +SHA1_RECOMPRESS(8) +#endif + +#ifdef DOSTORESTATE9 +SHA1_RECOMPRESS(9) +#endif + +#ifdef DOSTORESTATE10 +SHA1_RECOMPRESS(10) +#endif + +#ifdef DOSTORESTATE11 +SHA1_RECOMPRESS(11) +#endif + +#ifdef DOSTORESTATE12 +SHA1_RECOMPRESS(12) +#endif + +#ifdef DOSTORESTATE13 +SHA1_RECOMPRESS(13) +#endif + +#ifdef DOSTORESTATE14 +SHA1_RECOMPRESS(14) +#endif + +#ifdef DOSTORESTATE15 +SHA1_RECOMPRESS(15) +#endif + +#ifdef DOSTORESTATE16 +SHA1_RECOMPRESS(16) +#endif + +#ifdef DOSTORESTATE17 +SHA1_RECOMPRESS(17) +#endif + +#ifdef DOSTORESTATE18 +SHA1_RECOMPRESS(18) +#endif + +#ifdef DOSTORESTATE19 +SHA1_RECOMPRESS(19) +#endif + +#ifdef DOSTORESTATE20 +SHA1_RECOMPRESS(20) +#endif + +#ifdef DOSTORESTATE21 +SHA1_RECOMPRESS(21) +#endif + +#ifdef DOSTORESTATE22 +SHA1_RECOMPRESS(22) +#endif + +#ifdef DOSTORESTATE23 +SHA1_RECOMPRESS(23) +#endif + +#ifdef DOSTORESTATE24 +SHA1_RECOMPRESS(24) +#endif + +#ifdef DOSTORESTATE25 +SHA1_RECOMPRESS(25) +#endif + +#ifdef DOSTORESTATE26 +SHA1_RECOMPRESS(26) +#endif + +#ifdef DOSTORESTATE27 +SHA1_RECOMPRESS(27) +#endif + +#ifdef DOSTORESTATE28 +SHA1_RECOMPRESS(28) +#endif + +#ifdef DOSTORESTATE29 +SHA1_RECOMPRESS(29) +#endif + +#ifdef DOSTORESTATE30 +SHA1_RECOMPRESS(30) +#endif + +#ifdef DOSTORESTATE31 +SHA1_RECOMPRESS(31) +#endif + +#ifdef DOSTORESTATE32 +SHA1_RECOMPRESS(32) +#endif + +#ifdef DOSTORESTATE33 +SHA1_RECOMPRESS(33) +#endif + +#ifdef DOSTORESTATE34 +SHA1_RECOMPRESS(34) +#endif + +#ifdef DOSTORESTATE35 +SHA1_RECOMPRESS(35) +#endif + +#ifdef DOSTORESTATE36 +SHA1_RECOMPRESS(36) +#endif + +#ifdef DOSTORESTATE37 +SHA1_RECOMPRESS(37) +#endif + +#ifdef DOSTORESTATE38 +SHA1_RECOMPRESS(38) +#endif + +#ifdef DOSTORESTATE39 +SHA1_RECOMPRESS(39) +#endif + +#ifdef DOSTORESTATE40 +SHA1_RECOMPRESS(40) +#endif + +#ifdef DOSTORESTATE41 +SHA1_RECOMPRESS(41) +#endif + +#ifdef DOSTORESTATE42 +SHA1_RECOMPRESS(42) +#endif + +#ifdef DOSTORESTATE43 +SHA1_RECOMPRESS(43) +#endif + +#ifdef DOSTORESTATE44 +SHA1_RECOMPRESS(44) +#endif + +#ifdef DOSTORESTATE45 +SHA1_RECOMPRESS(45) +#endif + +#ifdef DOSTORESTATE46 +SHA1_RECOMPRESS(46) +#endif + +#ifdef DOSTORESTATE47 +SHA1_RECOMPRESS(47) +#endif + +#ifdef DOSTORESTATE48 +SHA1_RECOMPRESS(48) +#endif + +#ifdef DOSTORESTATE49 +SHA1_RECOMPRESS(49) +#endif + +#ifdef DOSTORESTATE50 +SHA1_RECOMPRESS(50) +#endif + +#ifdef DOSTORESTATE51 +SHA1_RECOMPRESS(51) +#endif + +#ifdef DOSTORESTATE52 +SHA1_RECOMPRESS(52) +#endif + +#ifdef DOSTORESTATE53 +SHA1_RECOMPRESS(53) +#endif + +#ifdef DOSTORESTATE54 +SHA1_RECOMPRESS(54) +#endif + +#ifdef DOSTORESTATE55 +SHA1_RECOMPRESS(55) +#endif + +#ifdef DOSTORESTATE56 +SHA1_RECOMPRESS(56) +#endif + +#ifdef DOSTORESTATE57 +SHA1_RECOMPRESS(57) +#endif + +#ifdef DOSTORESTATE58 +SHA1_RECOMPRESS(58) +#endif + +#ifdef DOSTORESTATE59 +SHA1_RECOMPRESS(59) +#endif + +#ifdef DOSTORESTATE60 +SHA1_RECOMPRESS(60) +#endif + +#ifdef DOSTORESTATE61 +SHA1_RECOMPRESS(61) +#endif + +#ifdef DOSTORESTATE62 +SHA1_RECOMPRESS(62) +#endif + +#ifdef DOSTORESTATE63 +SHA1_RECOMPRESS(63) +#endif + +#ifdef DOSTORESTATE64 +SHA1_RECOMPRESS(64) +#endif + +#ifdef DOSTORESTATE65 +SHA1_RECOMPRESS(65) +#endif + +#ifdef DOSTORESTATE66 +SHA1_RECOMPRESS(66) +#endif + +#ifdef DOSTORESTATE67 +SHA1_RECOMPRESS(67) +#endif + +#ifdef DOSTORESTATE68 +SHA1_RECOMPRESS(68) +#endif + +#ifdef DOSTORESTATE69 +SHA1_RECOMPRESS(69) +#endif + +#ifdef DOSTORESTATE70 +SHA1_RECOMPRESS(70) +#endif + +#ifdef DOSTORESTATE71 +SHA1_RECOMPRESS(71) +#endif + +#ifdef DOSTORESTATE72 +SHA1_RECOMPRESS(72) +#endif + +#ifdef DOSTORESTATE73 +SHA1_RECOMPRESS(73) +#endif + +#ifdef DOSTORESTATE74 +SHA1_RECOMPRESS(74) +#endif + +#ifdef DOSTORESTATE75 +SHA1_RECOMPRESS(75) +#endif + +#ifdef DOSTORESTATE76 +SHA1_RECOMPRESS(76) +#endif + +#ifdef DOSTORESTATE77 +SHA1_RECOMPRESS(77) +#endif + +#ifdef DOSTORESTATE78 +SHA1_RECOMPRESS(78) +#endif + +#ifdef DOSTORESTATE79 +SHA1_RECOMPRESS(79) +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +static void +sha1_recompression_step(uint32_t step, + uint32_t ihvin[5], + uint32_t ihvout[5], + const uint32_t me2[80], + const uint32_t state[5]) +{ + switch (step) { +#ifdef DOSTORESTATE0 + case 0: + sha1recompress_fast_0(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE1 + case 1: + sha1recompress_fast_1(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE2 + case 2: + sha1recompress_fast_2(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE3 + case 3: + sha1recompress_fast_3(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE4 + case 4: + sha1recompress_fast_4(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE5 + case 5: + sha1recompress_fast_5(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE6 + case 6: + sha1recompress_fast_6(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE7 + case 7: + sha1recompress_fast_7(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE8 + case 8: + sha1recompress_fast_8(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE9 + case 9: + sha1recompress_fast_9(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE10 + case 10: + sha1recompress_fast_10(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE11 + case 11: + sha1recompress_fast_11(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE12 + case 12: + sha1recompress_fast_12(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE13 + case 13: + sha1recompress_fast_13(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE14 + case 14: + sha1recompress_fast_14(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE15 + case 15: + sha1recompress_fast_15(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE16 + case 16: + sha1recompress_fast_16(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE17 + case 17: + sha1recompress_fast_17(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE18 + case 18: + sha1recompress_fast_18(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE19 + case 19: + sha1recompress_fast_19(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE20 + case 20: + sha1recompress_fast_20(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE21 + case 21: + sha1recompress_fast_21(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE22 + case 22: + sha1recompress_fast_22(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE23 + case 23: + sha1recompress_fast_23(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE24 + case 24: + sha1recompress_fast_24(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE25 + case 25: + sha1recompress_fast_25(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE26 + case 26: + sha1recompress_fast_26(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE27 + case 27: + sha1recompress_fast_27(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE28 + case 28: + sha1recompress_fast_28(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE29 + case 29: + sha1recompress_fast_29(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE30 + case 30: + sha1recompress_fast_30(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE31 + case 31: + sha1recompress_fast_31(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE32 + case 32: + sha1recompress_fast_32(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE33 + case 33: + sha1recompress_fast_33(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE34 + case 34: + sha1recompress_fast_34(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE35 + case 35: + sha1recompress_fast_35(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE36 + case 36: + sha1recompress_fast_36(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE37 + case 37: + sha1recompress_fast_37(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE38 + case 38: + sha1recompress_fast_38(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE39 + case 39: + sha1recompress_fast_39(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE40 + case 40: + sha1recompress_fast_40(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE41 + case 41: + sha1recompress_fast_41(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE42 + case 42: + sha1recompress_fast_42(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE43 + case 43: + sha1recompress_fast_43(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE44 + case 44: + sha1recompress_fast_44(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE45 + case 45: + sha1recompress_fast_45(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE46 + case 46: + sha1recompress_fast_46(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE47 + case 47: + sha1recompress_fast_47(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE48 + case 48: + sha1recompress_fast_48(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE49 + case 49: + sha1recompress_fast_49(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE50 + case 50: + sha1recompress_fast_50(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE51 + case 51: + sha1recompress_fast_51(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE52 + case 52: + sha1recompress_fast_52(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE53 + case 53: + sha1recompress_fast_53(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE54 + case 54: + sha1recompress_fast_54(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE55 + case 55: + sha1recompress_fast_55(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE56 + case 56: + sha1recompress_fast_56(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE57 + case 57: + sha1recompress_fast_57(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE58 + case 58: + sha1recompress_fast_58(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE59 + case 59: + sha1recompress_fast_59(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE60 + case 60: + sha1recompress_fast_60(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE61 + case 61: + sha1recompress_fast_61(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE62 + case 62: + sha1recompress_fast_62(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE63 + case 63: + sha1recompress_fast_63(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE64 + case 64: + sha1recompress_fast_64(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE65 + case 65: + sha1recompress_fast_65(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE66 + case 66: + sha1recompress_fast_66(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE67 + case 67: + sha1recompress_fast_67(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE68 + case 68: + sha1recompress_fast_68(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE69 + case 69: + sha1recompress_fast_69(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE70 + case 70: + sha1recompress_fast_70(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE71 + case 71: + sha1recompress_fast_71(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE72 + case 72: + sha1recompress_fast_72(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE73 + case 73: + sha1recompress_fast_73(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE74 + case 74: + sha1recompress_fast_74(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE75 + case 75: + sha1recompress_fast_75(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE76 + case 76: + sha1recompress_fast_76(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE77 + case 77: + sha1recompress_fast_77(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE78 + case 78: + sha1recompress_fast_78(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE79 + case 79: + sha1recompress_fast_79(ihvin, ihvout, me2, state); + break; +#endif + default: + abort(); + } +} + +static void +sha1_process(SHA1_CTX *ctx, const uint32_t block[16]) +{ + unsigned i, j; + uint32_t ubc_dv_mask[DVMASKSIZE] = {0xFFFFFFFF}; + uint32_t ihvtmp[5]; + + ctx->ihv1[0] = ctx->ihv[0]; + ctx->ihv1[1] = ctx->ihv[1]; + ctx->ihv1[2] = ctx->ihv[2]; + ctx->ihv1[3] = ctx->ihv[3]; + ctx->ihv1[4] = ctx->ihv[4]; + + sha1_compression_states(ctx->ihv, block, ctx->m1, ctx->states); + + if (ctx->detect_coll) { + if (ctx->ubc_check) { + ubc_check(ctx->m1, ubc_dv_mask); + } + + if (ubc_dv_mask[0] != 0) { + for (i = 0; sha1_dvs[i].dvType != 0; ++i) { + if (ubc_dv_mask[0] & ((uint32_t)(1) << sha1_dvs[i].maskb)) { + for (j = 0; j < 80; ++j) + ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j]; + + sha1_recompression_step(sha1_dvs[i].testt, + ctx->ihv2, + ihvtmp, + ctx->m2, + ctx->states[sha1_dvs[i].testt]); + + /* to verify SHA-1 collision detection code with collisions for + * reduced-step SHA-1 */ + if ((0 == ((ihvtmp[0] ^ ctx->ihv[0]) | (ihvtmp[1] ^ ctx->ihv[1]) | + (ihvtmp[2] ^ ctx->ihv[2]) | (ihvtmp[3] ^ ctx->ihv[3]) | + (ihvtmp[4] ^ ctx->ihv[4]))) || + (ctx->reduced_round_coll && + 0 == ((ctx->ihv1[0] ^ ctx->ihv2[0]) | (ctx->ihv1[1] ^ ctx->ihv2[1]) | + (ctx->ihv1[2] ^ ctx->ihv2[2]) | (ctx->ihv1[3] ^ ctx->ihv2[3]) | + (ctx->ihv1[4] ^ ctx->ihv2[4])))) { + ctx->found_collision = 1; + + if (ctx->safe_hash) { + sha1_compression_W(ctx->ihv, ctx->m1); + sha1_compression_W(ctx->ihv, ctx->m1); + } + + break; + } + } + } + } + } +} + +void +SHA1DCInit(SHA1_CTX *ctx) +{ + ctx->total = 0; + ctx->ihv[0] = 0x67452301; + ctx->ihv[1] = 0xEFCDAB89; + ctx->ihv[2] = 0x98BADCFE; + ctx->ihv[3] = 0x10325476; + ctx->ihv[4] = 0xC3D2E1F0; + ctx->found_collision = 0; + ctx->safe_hash = SHA1DC_INIT_SAFE_HASH_DEFAULT; + ctx->ubc_check = 1; + ctx->detect_coll = 1; + ctx->reduced_round_coll = 0; + ctx->callback = NULL; +} + +void +SHA1DCSetSafeHash(SHA1_CTX *ctx, int safehash) +{ + if (safehash) + ctx->safe_hash = 1; + else + ctx->safe_hash = 0; +} + +void +SHA1DCSetUseUBC(SHA1_CTX *ctx, int ubc_check) +{ + if (ubc_check) + ctx->ubc_check = 1; + else + ctx->ubc_check = 0; +} + +void +SHA1DCSetUseDetectColl(SHA1_CTX *ctx, int detect_coll) +{ + if (detect_coll) + ctx->detect_coll = 1; + else + ctx->detect_coll = 0; +} + +void +SHA1DCSetDetectReducedRoundCollision(SHA1_CTX *ctx, int reduced_round_coll) +{ + if (reduced_round_coll) + ctx->reduced_round_coll = 1; + else + ctx->reduced_round_coll = 0; +} + +void +SHA1DCSetCallback(SHA1_CTX *ctx, collision_block_callback callback) +{ + ctx->callback = callback; +} + +void +SHA1DCUpdate(SHA1_CTX *ctx, const char *buf, size_t len) +{ + unsigned left, fill; + + if (len == 0) + return; + + left = ctx->total & 63; + fill = 64 - left; + + if (left && len >= fill) { + ctx->total += fill; + memcpy(ctx->buffer + left, buf, fill); + sha1_process(ctx, (uint32_t *) (ctx->buffer)); + buf += fill; + len -= fill; + left = 0; + } + while (len >= 64) { + ctx->total += 64; + +#if defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) + sha1_process(ctx, (uint32_t *) (buf)); +#else + memcpy(ctx->buffer, buf, 64); + sha1_process(ctx, (uint32_t *) (ctx->buffer)); +#endif /* defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) */ + buf += 64; + len -= 64; + } + if (len > 0) { + ctx->total += len; + memcpy(ctx->buffer + left, buf, len); + } +} + +static const unsigned char sha1_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +int +SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx) +{ + uint32_t last = ctx->total & 63; + uint32_t padn = (last < 56) ? (56 - last) : (120 - last); + uint64_t total; + SHA1DCUpdate(ctx, (const char *) (sha1_padding), padn); + + total = ctx->total - padn; + total <<= 3; + ctx->buffer[56] = (unsigned char) (total >> 56); + ctx->buffer[57] = (unsigned char) (total >> 48); + ctx->buffer[58] = (unsigned char) (total >> 40); + ctx->buffer[59] = (unsigned char) (total >> 32); + ctx->buffer[60] = (unsigned char) (total >> 24); + ctx->buffer[61] = (unsigned char) (total >> 16); + ctx->buffer[62] = (unsigned char) (total >> 8); + ctx->buffer[63] = (unsigned char) (total); + sha1_process(ctx, (uint32_t *) (ctx->buffer)); + output[0] = (unsigned char) (ctx->ihv[0] >> 24); + output[1] = (unsigned char) (ctx->ihv[0] >> 16); + output[2] = (unsigned char) (ctx->ihv[0] >> 8); + output[3] = (unsigned char) (ctx->ihv[0]); + output[4] = (unsigned char) (ctx->ihv[1] >> 24); + output[5] = (unsigned char) (ctx->ihv[1] >> 16); + output[6] = (unsigned char) (ctx->ihv[1] >> 8); + output[7] = (unsigned char) (ctx->ihv[1]); + output[8] = (unsigned char) (ctx->ihv[2] >> 24); + output[9] = (unsigned char) (ctx->ihv[2] >> 16); + output[10] = (unsigned char) (ctx->ihv[2] >> 8); + output[11] = (unsigned char) (ctx->ihv[2]); + output[12] = (unsigned char) (ctx->ihv[3] >> 24); + output[13] = (unsigned char) (ctx->ihv[3] >> 16); + output[14] = (unsigned char) (ctx->ihv[3] >> 8); + output[15] = (unsigned char) (ctx->ihv[3]); + output[16] = (unsigned char) (ctx->ihv[4] >> 24); + output[17] = (unsigned char) (ctx->ihv[4] >> 16); + output[18] = (unsigned char) (ctx->ihv[4] >> 8); + output[19] = (unsigned char) (ctx->ihv[4]); + return ctx->found_collision; +} + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/sha1.h 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,122 @@ +/*** + * Copyright 2017 Marc Stevens , Dan Shumow + * Distributed under the MIT Software License. + * See accompanying file LICENSE.txt or copy at + * https://opensource.org/licenses/MIT + ***/ + +#ifndef SHA1DC_SHA1_H +#define SHA1DC_SHA1_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#endif + +/* sha-1 compression function that takes an already expanded message, and additionally store + * intermediate states */ +/* only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is + * defined in ubc_check.h */ +void sha1_compression_states(uint32_t[5], const uint32_t[16], uint32_t[80], uint32_t[80][5]); + +/* +// Function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const +uint32_t me2[80], const uint32_t state[5]). +// Where 0 <= T < 80 +// me2 is an expanded message (the expansion of an original message block XOR'ed with a +disturbance vector's message block difference.) +// state is the internal state (a,b,c,d,e) before step T of the SHA-1 compression +function while processing the original message block. +// The function will return: +// ihvin: The reconstructed input chaining value. +// ihvout: The reconstructed output chaining value. +*/ +typedef void (*sha1_recompression_type)(uint32_t *, + uint32_t *, + const uint32_t *, + const uint32_t *); + +/* A callback function type that can be set to be called when a collision block has been found: + */ +/* void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t + * ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) */ +typedef void (*collision_block_callback)( + uint64_t, const uint32_t *, const uint32_t *, const uint32_t *, const uint32_t *); + +/* The SHA-1 context. */ +typedef struct { + uint64_t total; + uint32_t ihv[5]; + unsigned char buffer[64]; + int found_collision; + int safe_hash; + int detect_coll; + int ubc_check; + int reduced_round_coll; + collision_block_callback callback; + + uint32_t ihv1[5]; + uint32_t ihv2[5]; + uint32_t m1[80]; + uint32_t m2[80]; + uint32_t states[80][5]; +} SHA1_CTX; + +/* Initialize SHA-1 context. */ +void SHA1DCInit(SHA1_CTX *); + +/* + Function to enable safe SHA-1 hashing: + Collision attacks are thwarted by hashing a detected near-collision block 3 times. + Think of it as extending SHA-1 from 80-steps to 240-steps for such blocks: + The best collision attacks against SHA-1 have complexity about 2^60, + thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would be + 2^180. An attacker would be better off using a generic birthday search of complexity 2^80. + + Enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no + collision attack was detected, but it will result in a different SHA-1 hash for messages + where a collision attack was detected. This will automatically invalidate SHA-1 based + digital signature forgeries. Enabled by default. +*/ +void SHA1DCSetSafeHash(SHA1_CTX *, int); + +/* + Function to disable or enable the use of Unavoidable Bitconditions (provides a significant + speed up). Enabled by default + */ +void SHA1DCSetUseUBC(SHA1_CTX *, int); + +/* + Function to disable or enable the use of Collision Detection. + Enabled by default. + */ +void SHA1DCSetUseDetectColl(SHA1_CTX *, int); + +/* function to disable or enable the detection of reduced-round SHA-1 collisions */ +/* disabled by default */ +void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX *, int); + +/* function to set a callback function, pass NULL to disable */ +/* by default no callback set */ +void SHA1DCSetCallback(SHA1_CTX *, collision_block_callback); + +/* update SHA-1 context with buffer contents */ +void SHA1DCUpdate(SHA1_CTX *, const char *, size_t); + +/* obtain SHA-1 hash from SHA-1 context */ +/* returns: 0 = no collision detected, otherwise = collision found => warn user for active + * attack */ +int SHA1DCFinal(unsigned char[20], SHA1_CTX *); + +#if defined(__cplusplus) +} +#endif + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H +#endif + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.c thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.c --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.c 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.c 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,908 @@ +/*** + * Copyright 2017 Marc Stevens , Dan Shumow + * Distributed under the MIT Software License. + * See accompanying file LICENSE.txt or copy at + * https://opensource.org/licenses/MIT + ***/ + +/* +// this file was generated by the 'parse_bitrel' program in the tools section +// using the data files from directory 'tools/data/3565' +// +// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check +// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) +// dm[80] is the expanded message block XOR-difference defined by the DV +// testt is the step to do the recompression from for collision detection +// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check +// +// ubc_check takes as input an expanded message block and verifies the unavoidable +bitconditions for all listed DVs +// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions +for that DV have been met +// thus one needs to do the recompression check for each DV that has its bit set +// +// ubc_check is programmatically generated and the unavoidable bitconditions have been +hardcoded +// a directly verifiable version named ubc_check_verify can be found in ubc_check_verify.c +// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in +the tools section +*/ + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#endif +#ifdef SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C +#include SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C +#endif +#include "ubc_check.h" + +static const uint32_t DV_I_43_0_bit = (uint32_t)(1) << 0; +static const uint32_t DV_I_44_0_bit = (uint32_t)(1) << 1; +static const uint32_t DV_I_45_0_bit = (uint32_t)(1) << 2; +static const uint32_t DV_I_46_0_bit = (uint32_t)(1) << 3; +static const uint32_t DV_I_46_2_bit = (uint32_t)(1) << 4; +static const uint32_t DV_I_47_0_bit = (uint32_t)(1) << 5; +static const uint32_t DV_I_47_2_bit = (uint32_t)(1) << 6; +static const uint32_t DV_I_48_0_bit = (uint32_t)(1) << 7; +static const uint32_t DV_I_48_2_bit = (uint32_t)(1) << 8; +static const uint32_t DV_I_49_0_bit = (uint32_t)(1) << 9; +static const uint32_t DV_I_49_2_bit = (uint32_t)(1) << 10; +static const uint32_t DV_I_50_0_bit = (uint32_t)(1) << 11; +static const uint32_t DV_I_50_2_bit = (uint32_t)(1) << 12; +static const uint32_t DV_I_51_0_bit = (uint32_t)(1) << 13; +static const uint32_t DV_I_51_2_bit = (uint32_t)(1) << 14; +static const uint32_t DV_I_52_0_bit = (uint32_t)(1) << 15; +static const uint32_t DV_II_45_0_bit = (uint32_t)(1) << 16; +static const uint32_t DV_II_46_0_bit = (uint32_t)(1) << 17; +static const uint32_t DV_II_46_2_bit = (uint32_t)(1) << 18; +static const uint32_t DV_II_47_0_bit = (uint32_t)(1) << 19; +static const uint32_t DV_II_48_0_bit = (uint32_t)(1) << 20; +static const uint32_t DV_II_49_0_bit = (uint32_t)(1) << 21; +static const uint32_t DV_II_49_2_bit = (uint32_t)(1) << 22; +static const uint32_t DV_II_50_0_bit = (uint32_t)(1) << 23; +static const uint32_t DV_II_50_2_bit = (uint32_t)(1) << 24; +static const uint32_t DV_II_51_0_bit = (uint32_t)(1) << 25; +static const uint32_t DV_II_51_2_bit = (uint32_t)(1) << 26; +static const uint32_t DV_II_52_0_bit = (uint32_t)(1) << 27; +static const uint32_t DV_II_53_0_bit = (uint32_t)(1) << 28; +static const uint32_t DV_II_54_0_bit = (uint32_t)(1) << 29; +static const uint32_t DV_II_55_0_bit = (uint32_t)(1) << 30; +static const uint32_t DV_II_56_0_bit = (uint32_t)(1) << 31; + +dv_info_t sha1_dvs[] = { + {1, 43, 0, 58, 0, 0, {0x08000000, 0x9800000c, 0xd8000010, 0x08000010, 0xb8000010, 0x98000000, + 0x60000000, 0x00000008, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, + 0x28000000, 0x20000010, 0x48000000, 0x08000018, 0x60000000, 0x90000010, + 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, + 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, + 0x90000010, 0x90000000, 0x80000000, 0x00000010, 0xa0000000, 0x20000000, + 0xa0000000, 0x20000010, 0x00000000, 0x20000010, 0x20000000, 0x00000010, + 0x20000000, 0x00000010, 0xa0000000, 0x00000000, 0x20000000, 0x20000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000020, + 0x00000001, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, + 0x80000006, 0x00000049, 0x00000103, 0x80000009, 0x80000012, 0x80000202, + 0x00000018, 0x00000164, 0x00000408, 0x800000e6, 0x8000004c, 0x00000803, + 0x80000161, 0x80000599}}, + {1, 44, 0, 58, 0, 1, {0xb4000008, 0x08000000, 0x9800000c, 0xd8000010, 0x08000010, 0xb8000010, + 0x98000000, 0x60000000, 0x00000008, 0xc0000000, 0x90000014, 0x10000010, + 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x08000018, 0x60000000, + 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, + 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, + 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x00000010, 0xa0000000, + 0x20000000, 0xa0000000, 0x20000010, 0x00000000, 0x20000010, 0x20000000, + 0x00000010, 0x20000000, 0x00000010, 0xa0000000, 0x00000000, 0x20000000, + 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000020, 0x00000001, 0x40000002, 0x40000040, 0x40000002, 0x80000004, + 0x80000080, 0x80000006, 0x00000049, 0x00000103, 0x80000009, 0x80000012, + 0x80000202, 0x00000018, 0x00000164, 0x00000408, 0x800000e6, 0x8000004c, + 0x00000803, 0x80000161}}, + {1, 45, 0, 58, 0, 2, {0xf4000014, 0xb4000008, 0x08000000, 0x9800000c, 0xd8000010, 0x08000010, + 0xb8000010, 0x98000000, 0x60000000, 0x00000008, 0xc0000000, 0x90000014, + 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x08000018, + 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, + 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, + 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x00000010, + 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0x00000000, 0x20000010, + 0x20000000, 0x00000010, 0x20000000, 0x00000010, 0xa0000000, 0x00000000, + 0x20000000, 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000020, 0x00000001, 0x40000002, 0x40000040, 0x40000002, + 0x80000004, 0x80000080, 0x80000006, 0x00000049, 0x00000103, 0x80000009, + 0x80000012, 0x80000202, 0x00000018, 0x00000164, 0x00000408, 0x800000e6, + 0x8000004c, 0x00000803}}, + {1, 46, 0, 58, 0, 3, {0x2c000010, 0xf4000014, 0xb4000008, 0x08000000, 0x9800000c, 0xd8000010, + 0x08000010, 0xb8000010, 0x98000000, 0x60000000, 0x00000008, 0xc0000000, + 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, + 0x08000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, + 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, + 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, + 0x00000010, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0x00000000, + 0x20000010, 0x20000000, 0x00000010, 0x20000000, 0x00000010, 0xa0000000, + 0x00000000, 0x20000000, 0x20000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000020, 0x00000001, 0x40000002, 0x40000040, + 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x00000049, 0x00000103, + 0x80000009, 0x80000012, 0x80000202, 0x00000018, 0x00000164, 0x00000408, + 0x800000e6, 0x8000004c}}, + {1, 46, 2, 58, 0, 4, {0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, 0x60000043, + 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x00000020, 0x00000003, + 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, + 0x20000060, 0x80000001, 0x40000042, 0xc0000043, 0x40000022, 0x00000003, + 0x40000042, 0xc0000043, 0xc0000022, 0x00000001, 0x40000002, 0xc0000043, + 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x00000002, + 0x00000040, 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0x00000000, + 0x80000040, 0x80000000, 0x00000040, 0x80000000, 0x00000040, 0x80000002, + 0x00000000, 0x80000000, 0x80000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000080, 0x00000004, 0x00000009, 0x00000101, + 0x00000009, 0x00000012, 0x00000202, 0x0000001a, 0x00000124, 0x0000040c, + 0x00000026, 0x0000004a, 0x0000080a, 0x00000060, 0x00000590, 0x00001020, + 0x0000039a, 0x00000132}}, + {1, 47, 0, 58, 0, 5, {0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x08000000, 0x9800000c, + 0xd8000010, 0x08000010, 0xb8000010, 0x98000000, 0x60000000, 0x00000008, + 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, + 0x48000000, 0x08000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, + 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, + 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, + 0x80000000, 0x00000010, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, + 0x00000000, 0x20000010, 0x20000000, 0x00000010, 0x20000000, 0x00000010, + 0xa0000000, 0x00000000, 0x20000000, 0x20000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000020, 0x00000001, 0x40000002, + 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x00000049, + 0x00000103, 0x80000009, 0x80000012, 0x80000202, 0x00000018, 0x00000164, + 0x00000408, 0x800000e6}}, + {1, 47, 2, 58, 0, 6, {0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, + 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x00000020, + 0x00000003, 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, + 0x20000001, 0x20000060, 0x80000001, 0x40000042, 0xc0000043, 0x40000022, + 0x00000003, 0x40000042, 0xc0000043, 0xc0000022, 0x00000001, 0x40000002, + 0xc0000043, 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, + 0x00000002, 0x00000040, 0x80000002, 0x80000000, 0x80000002, 0x80000040, + 0x00000000, 0x80000040, 0x80000000, 0x00000040, 0x80000000, 0x00000040, + 0x80000002, 0x00000000, 0x80000000, 0x80000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000004, 0x00000080, 0x00000004, 0x00000009, + 0x00000101, 0x00000009, 0x00000012, 0x00000202, 0x0000001a, 0x00000124, + 0x0000040c, 0x00000026, 0x0000004a, 0x0000080a, 0x00000060, 0x00000590, + 0x00001020, 0x0000039a}}, + {1, 48, 0, 58, 0, 7, {0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x08000000, + 0x9800000c, 0xd8000010, 0x08000010, 0xb8000010, 0x98000000, 0x60000000, + 0x00000008, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, + 0x20000010, 0x48000000, 0x08000018, 0x60000000, 0x90000010, 0xf0000010, + 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, + 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, + 0x90000000, 0x80000000, 0x00000010, 0xa0000000, 0x20000000, 0xa0000000, + 0x20000010, 0x00000000, 0x20000010, 0x20000000, 0x00000010, 0x20000000, + 0x00000010, 0xa0000000, 0x00000000, 0x20000000, 0x20000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000020, 0x00000001, + 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, + 0x00000049, 0x00000103, 0x80000009, 0x80000012, 0x80000202, 0x00000018, + 0x00000164, 0x00000408}}, + {1, 48, 2, 58, 0, 8, {0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, + 0x60000032, 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, + 0x00000020, 0x00000003, 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, + 0x80000040, 0x20000001, 0x20000060, 0x80000001, 0x40000042, 0xc0000043, + 0x40000022, 0x00000003, 0x40000042, 0xc0000043, 0xc0000022, 0x00000001, + 0x40000002, 0xc0000043, 0x40000062, 0x80000001, 0x40000042, 0x40000042, + 0x40000002, 0x00000002, 0x00000040, 0x80000002, 0x80000000, 0x80000002, + 0x80000040, 0x00000000, 0x80000040, 0x80000000, 0x00000040, 0x80000000, + 0x00000040, 0x80000002, 0x00000000, 0x80000000, 0x80000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000080, 0x00000004, + 0x00000009, 0x00000101, 0x00000009, 0x00000012, 0x00000202, 0x0000001a, + 0x00000124, 0x0000040c, 0x00000026, 0x0000004a, 0x0000080a, 0x00000060, + 0x00000590, 0x00001020}}, + {1, 49, 0, 58, 0, 9, {0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, + 0x08000000, 0x9800000c, 0xd8000010, 0x08000010, 0xb8000010, 0x98000000, + 0x60000000, 0x00000008, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, + 0x28000000, 0x20000010, 0x48000000, 0x08000018, 0x60000000, 0x90000010, + 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, + 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, + 0x90000010, 0x90000000, 0x80000000, 0x00000010, 0xa0000000, 0x20000000, + 0xa0000000, 0x20000010, 0x00000000, 0x20000010, 0x20000000, 0x00000010, + 0x20000000, 0x00000010, 0xa0000000, 0x00000000, 0x20000000, 0x20000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000020, + 0x00000001, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, + 0x80000006, 0x00000049, 0x00000103, 0x80000009, 0x80000012, 0x80000202, + 0x00000018, 0x00000164}}, + {1, 49, 2, 58, 0, 10, {0x60000000, 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, + 0xd0000022, 0x20000000, 0x60000032, 0x60000043, 0x20000040, + 0xe0000042, 0x60000002, 0x80000001, 0x00000020, 0x00000003, + 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, + 0x20000001, 0x20000060, 0x80000001, 0x40000042, 0xc0000043, + 0x40000022, 0x00000003, 0x40000042, 0xc0000043, 0xc0000022, + 0x00000001, 0x40000002, 0xc0000043, 0x40000062, 0x80000001, + 0x40000042, 0x40000042, 0x40000002, 0x00000002, 0x00000040, + 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0x00000000, + 0x80000040, 0x80000000, 0x00000040, 0x80000000, 0x00000040, + 0x80000002, 0x00000000, 0x80000000, 0x80000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000080, 0x00000004, 0x00000009, 0x00000101, 0x00000009, + 0x00000012, 0x00000202, 0x0000001a, 0x00000124, 0x0000040c, + 0x00000026, 0x0000004a, 0x0000080a, 0x00000060, 0x00000590}}, + {1, 50, 0, 65, 0, 11, {0x0800000c, 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, + 0xf4000014, 0xb4000008, 0x08000000, 0x9800000c, 0xd8000010, + 0x08000010, 0xb8000010, 0x98000000, 0x60000000, 0x00000008, + 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, + 0x20000010, 0x48000000, 0x08000018, 0x60000000, 0x90000010, + 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, + 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, + 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, + 0x00000010, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, + 0x00000000, 0x20000010, 0x20000000, 0x00000010, 0x20000000, + 0x00000010, 0xa0000000, 0x00000000, 0x20000000, 0x20000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000020, 0x00000001, 0x40000002, 0x40000040, + 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x00000049, + 0x00000103, 0x80000009, 0x80000012, 0x80000202, 0x00000018}}, + {1, 50, 2, 65, 0, 12, {0x20000030, 0x60000000, 0xe000002a, 0x20000043, 0xb0000040, + 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, 0x60000043, + 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x00000020, + 0x00000003, 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, + 0x80000040, 0x20000001, 0x20000060, 0x80000001, 0x40000042, + 0xc0000043, 0x40000022, 0x00000003, 0x40000042, 0xc0000043, + 0xc0000022, 0x00000001, 0x40000002, 0xc0000043, 0x40000062, + 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x00000002, + 0x00000040, 0x80000002, 0x80000000, 0x80000002, 0x80000040, + 0x00000000, 0x80000040, 0x80000000, 0x00000040, 0x80000000, + 0x00000040, 0x80000002, 0x00000000, 0x80000000, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000080, 0x00000004, 0x00000009, 0x00000101, + 0x00000009, 0x00000012, 0x00000202, 0x0000001a, 0x00000124, + 0x0000040c, 0x00000026, 0x0000004a, 0x0000080a, 0x00000060}}, + {1, 51, 0, 65, 0, 13, {0xe8000000, 0x0800000c, 0x18000000, 0xb800000a, 0xc8000010, + 0x2c000010, 0xf4000014, 0xb4000008, 0x08000000, 0x9800000c, + 0xd8000010, 0x08000010, 0xb8000010, 0x98000000, 0x60000000, + 0x00000008, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, + 0x28000000, 0x20000010, 0x48000000, 0x08000018, 0x60000000, + 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, + 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, + 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, + 0x80000000, 0x00000010, 0xa0000000, 0x20000000, 0xa0000000, + 0x20000010, 0x00000000, 0x20000010, 0x20000000, 0x00000010, + 0x20000000, 0x00000010, 0xa0000000, 0x00000000, 0x20000000, + 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000020, 0x00000001, 0x40000002, + 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, + 0x00000049, 0x00000103, 0x80000009, 0x80000012, 0x80000202}}, + {1, 51, 2, 65, 0, 14, {0xa0000003, 0x20000030, 0x60000000, 0xe000002a, 0x20000043, + 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, + 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, + 0x00000020, 0x00000003, 0x40000052, 0x40000040, 0xe0000052, + 0xa0000000, 0x80000040, 0x20000001, 0x20000060, 0x80000001, + 0x40000042, 0xc0000043, 0x40000022, 0x00000003, 0x40000042, + 0xc0000043, 0xc0000022, 0x00000001, 0x40000002, 0xc0000043, + 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, + 0x00000002, 0x00000040, 0x80000002, 0x80000000, 0x80000002, + 0x80000040, 0x00000000, 0x80000040, 0x80000000, 0x00000040, + 0x80000000, 0x00000040, 0x80000002, 0x00000000, 0x80000000, + 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000080, 0x00000004, 0x00000009, + 0x00000101, 0x00000009, 0x00000012, 0x00000202, 0x0000001a, + 0x00000124, 0x0000040c, 0x00000026, 0x0000004a, 0x0000080a}}, + {1, 52, 0, 65, 0, 15, {0x04000010, 0xe8000000, 0x0800000c, 0x18000000, 0xb800000a, + 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x08000000, + 0x9800000c, 0xd8000010, 0x08000010, 0xb8000010, 0x98000000, + 0x60000000, 0x00000008, 0xc0000000, 0x90000014, 0x10000010, + 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x08000018, + 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, + 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, + 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, + 0x90000000, 0x80000000, 0x00000010, 0xa0000000, 0x20000000, + 0xa0000000, 0x20000010, 0x00000000, 0x20000010, 0x20000000, + 0x00000010, 0x20000000, 0x00000010, 0xa0000000, 0x00000000, + 0x20000000, 0x20000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000020, 0x00000001, + 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, + 0x80000006, 0x00000049, 0x00000103, 0x80000009, 0x80000012}}, + {2, 45, 0, 58, 0, 16, {0xec000014, 0x0c000002, 0xc0000010, 0xb400001c, 0x2c000004, + 0xbc000018, 0xb0000010, 0x0000000c, 0xb8000010, 0x08000018, + 0x78000010, 0x08000014, 0x70000010, 0xb800001c, 0xe8000000, + 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, + 0xb8000010, 0x98000010, 0xa0000000, 0x00000000, 0x00000000, + 0x20000000, 0x80000000, 0x00000010, 0x00000000, 0x20000010, + 0x20000000, 0x00000010, 0x60000000, 0x00000018, 0xe0000000, + 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, + 0xa0000000, 0x00000010, 0x80000000, 0x20000000, 0x20000000, + 0x20000000, 0x80000000, 0x00000010, 0x00000000, 0x20000010, + 0xa0000000, 0x00000000, 0x20000000, 0x20000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000020, 0x00000001, 0x40000002, 0x40000041, + 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, + 0x80000107, 0x00000089, 0x00000014, 0x8000024b, 0x0000011b, + 0x8000016d, 0x8000041a, 0x000002e4, 0x80000054, 0x00000967}}, + {2, 46, 0, 58, 0, 17, {0x2400001c, 0xec000014, 0x0c000002, 0xc0000010, 0xb400001c, + 0x2c000004, 0xbc000018, 0xb0000010, 0x0000000c, 0xb8000010, + 0x08000018, 0x78000010, 0x08000014, 0x70000010, 0xb800001c, + 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, + 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0x00000000, + 0x00000000, 0x20000000, 0x80000000, 0x00000010, 0x00000000, + 0x20000010, 0x20000000, 0x00000010, 0x60000000, 0x00000018, + 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, + 0x20000000, 0xa0000000, 0x00000010, 0x80000000, 0x20000000, + 0x20000000, 0x20000000, 0x80000000, 0x00000010, 0x00000000, + 0x20000010, 0xa0000000, 0x00000000, 0x20000000, 0x20000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000020, 0x00000001, 0x40000002, + 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, + 0x4000004b, 0x80000107, 0x00000089, 0x00000014, 0x8000024b, + 0x0000011b, 0x8000016d, 0x8000041a, 0x000002e4, 0x80000054}}, + {2, 46, 2, 58, 0, 18, {0x90000070, 0xb0000053, 0x30000008, 0x00000043, 0xd0000072, + 0xb0000010, 0xf0000062, 0xc0000042, 0x00000030, 0xe0000042, + 0x20000060, 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, + 0xa0000003, 0xc0000012, 0x60000041, 0xc0000032, 0x20000001, + 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0x00000000, + 0x00000000, 0x80000000, 0x00000002, 0x00000040, 0x00000000, + 0x80000040, 0x80000000, 0x00000040, 0x80000001, 0x00000060, + 0x80000003, 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, + 0x80000000, 0x80000002, 0x00000040, 0x00000002, 0x80000000, + 0x80000000, 0x80000000, 0x00000002, 0x00000040, 0x00000000, + 0x80000040, 0x80000002, 0x00000000, 0x80000000, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000080, 0x00000004, 0x00000009, + 0x00000105, 0x00000089, 0x00000016, 0x0000020b, 0x0000011b, + 0x0000012d, 0x0000041e, 0x00000224, 0x00000050, 0x0000092e, + 0x0000046c, 0x000005b6, 0x0000106a, 0x00000b90, 0x00000152}}, + {2, 47, 0, 58, 0, 19, {0x20000010, 0x2400001c, 0xec000014, 0x0c000002, 0xc0000010, + 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0x0000000c, + 0xb8000010, 0x08000018, 0x78000010, 0x08000014, 0x70000010, + 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, + 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, + 0x00000000, 0x00000000, 0x20000000, 0x80000000, 0x00000010, + 0x00000000, 0x20000010, 0x20000000, 0x00000010, 0x60000000, + 0x00000018, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, + 0x20000000, 0x20000000, 0xa0000000, 0x00000010, 0x80000000, + 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x00000010, + 0x00000000, 0x20000010, 0xa0000000, 0x00000000, 0x20000000, + 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000020, 0x00000001, + 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, + 0xc0000046, 0x4000004b, 0x80000107, 0x00000089, 0x00000014, + 0x8000024b, 0x0000011b, 0x8000016d, 0x8000041a, 0x000002e4}}, + {2, 48, 0, 58, 0, 20, {0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0x0c000002, + 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, + 0x0000000c, 0xb8000010, 0x08000018, 0x78000010, 0x08000014, + 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, + 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, + 0xa0000000, 0x00000000, 0x00000000, 0x20000000, 0x80000000, + 0x00000010, 0x00000000, 0x20000010, 0x20000000, 0x00000010, + 0x60000000, 0x00000018, 0xe0000000, 0x90000000, 0x30000010, + 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x00000010, + 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, + 0x00000010, 0x00000000, 0x20000010, 0xa0000000, 0x00000000, + 0x20000000, 0x20000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000020, + 0x00000001, 0x40000002, 0x40000041, 0x40000022, 0x80000005, + 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, 0x00000089, + 0x00000014, 0x8000024b, 0x0000011b, 0x8000016d, 0x8000041a}}, + {2, 49, 0, 58, 0, 21, {0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, + 0x0c000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, + 0xb0000010, 0x0000000c, 0xb8000010, 0x08000018, 0x78000010, + 0x08000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, + 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, + 0x98000010, 0xa0000000, 0x00000000, 0x00000000, 0x20000000, + 0x80000000, 0x00000010, 0x00000000, 0x20000010, 0x20000000, + 0x00000010, 0x60000000, 0x00000018, 0xe0000000, 0x90000000, + 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, + 0x00000010, 0x80000000, 0x20000000, 0x20000000, 0x20000000, + 0x80000000, 0x00000010, 0x00000000, 0x20000010, 0xa0000000, + 0x00000000, 0x20000000, 0x20000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000020, 0x00000001, 0x40000002, 0x40000041, 0x40000022, + 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, + 0x00000089, 0x00000014, 0x8000024b, 0x0000011b, 0x8000016d}}, + {2, 49, 2, 58, 0, 22, {0xf0000010, 0xf000006a, 0x80000040, 0x90000070, 0xb0000053, + 0x30000008, 0x00000043, 0xd0000072, 0xb0000010, 0xf0000062, + 0xc0000042, 0x00000030, 0xe0000042, 0x20000060, 0xe0000041, + 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, 0xc0000012, + 0x60000041, 0xc0000032, 0x20000001, 0xc0000002, 0xe0000042, + 0x60000042, 0x80000002, 0x00000000, 0x00000000, 0x80000000, + 0x00000002, 0x00000040, 0x00000000, 0x80000040, 0x80000000, + 0x00000040, 0x80000001, 0x00000060, 0x80000003, 0x40000002, + 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, 0x80000002, + 0x00000040, 0x00000002, 0x80000000, 0x80000000, 0x80000000, + 0x00000002, 0x00000040, 0x00000000, 0x80000040, 0x80000002, + 0x00000000, 0x80000000, 0x80000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000080, 0x00000004, 0x00000009, 0x00000105, 0x00000089, + 0x00000016, 0x0000020b, 0x0000011b, 0x0000012d, 0x0000041e, + 0x00000224, 0x00000050, 0x0000092e, 0x0000046c, 0x000005b6}}, + {2, 50, 0, 65, 0, 23, {0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, + 0xec000014, 0x0c000002, 0xc0000010, 0xb400001c, 0x2c000004, + 0xbc000018, 0xb0000010, 0x0000000c, 0xb8000010, 0x08000018, + 0x78000010, 0x08000014, 0x70000010, 0xb800001c, 0xe8000000, + 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, + 0xb8000010, 0x98000010, 0xa0000000, 0x00000000, 0x00000000, + 0x20000000, 0x80000000, 0x00000010, 0x00000000, 0x20000010, + 0x20000000, 0x00000010, 0x60000000, 0x00000018, 0xe0000000, + 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, + 0xa0000000, 0x00000010, 0x80000000, 0x20000000, 0x20000000, + 0x20000000, 0x80000000, 0x00000010, 0x00000000, 0x20000010, + 0xa0000000, 0x00000000, 0x20000000, 0x20000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000020, 0x00000001, 0x40000002, 0x40000041, + 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, + 0x80000107, 0x00000089, 0x00000014, 0x8000024b, 0x0000011b}}, + {2, 50, 2, 65, 0, 24, {0xd0000072, 0xf0000010, 0xf000006a, 0x80000040, 0x90000070, + 0xb0000053, 0x30000008, 0x00000043, 0xd0000072, 0xb0000010, + 0xf0000062, 0xc0000042, 0x00000030, 0xe0000042, 0x20000060, + 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, + 0xc0000012, 0x60000041, 0xc0000032, 0x20000001, 0xc0000002, + 0xe0000042, 0x60000042, 0x80000002, 0x00000000, 0x00000000, + 0x80000000, 0x00000002, 0x00000040, 0x00000000, 0x80000040, + 0x80000000, 0x00000040, 0x80000001, 0x00000060, 0x80000003, + 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, + 0x80000002, 0x00000040, 0x00000002, 0x80000000, 0x80000000, + 0x80000000, 0x00000002, 0x00000040, 0x00000000, 0x80000040, + 0x80000002, 0x00000000, 0x80000000, 0x80000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000080, 0x00000004, 0x00000009, 0x00000105, + 0x00000089, 0x00000016, 0x0000020b, 0x0000011b, 0x0000012d, + 0x0000041e, 0x00000224, 0x00000050, 0x0000092e, 0x0000046c}}, + {2, 51, 0, 65, 0, 25, {0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, + 0x2400001c, 0xec000014, 0x0c000002, 0xc0000010, 0xb400001c, + 0x2c000004, 0xbc000018, 0xb0000010, 0x0000000c, 0xb8000010, + 0x08000018, 0x78000010, 0x08000014, 0x70000010, 0xb800001c, + 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, + 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0x00000000, + 0x00000000, 0x20000000, 0x80000000, 0x00000010, 0x00000000, + 0x20000010, 0x20000000, 0x00000010, 0x60000000, 0x00000018, + 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, + 0x20000000, 0xa0000000, 0x00000010, 0x80000000, 0x20000000, + 0x20000000, 0x20000000, 0x80000000, 0x00000010, 0x00000000, + 0x20000010, 0xa0000000, 0x00000000, 0x20000000, 0x20000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000020, 0x00000001, 0x40000002, + 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, + 0x4000004b, 0x80000107, 0x00000089, 0x00000014, 0x8000024b}}, + {2, 51, 2, 65, 0, 26, {0x00000043, 0xd0000072, 0xf0000010, 0xf000006a, 0x80000040, + 0x90000070, 0xb0000053, 0x30000008, 0x00000043, 0xd0000072, + 0xb0000010, 0xf0000062, 0xc0000042, 0x00000030, 0xe0000042, + 0x20000060, 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, + 0xa0000003, 0xc0000012, 0x60000041, 0xc0000032, 0x20000001, + 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0x00000000, + 0x00000000, 0x80000000, 0x00000002, 0x00000040, 0x00000000, + 0x80000040, 0x80000000, 0x00000040, 0x80000001, 0x00000060, + 0x80000003, 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, + 0x80000000, 0x80000002, 0x00000040, 0x00000002, 0x80000000, + 0x80000000, 0x80000000, 0x00000002, 0x00000040, 0x00000000, + 0x80000040, 0x80000002, 0x00000000, 0x80000000, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000080, 0x00000004, 0x00000009, + 0x00000105, 0x00000089, 0x00000016, 0x0000020b, 0x0000011b, + 0x0000012d, 0x0000041e, 0x00000224, 0x00000050, 0x0000092e}}, + {2, 52, 0, 65, 0, 27, {0x0c000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, + 0x20000010, 0x2400001c, 0xec000014, 0x0c000002, 0xc0000010, + 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0x0000000c, + 0xb8000010, 0x08000018, 0x78000010, 0x08000014, 0x70000010, + 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, + 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, + 0x00000000, 0x00000000, 0x20000000, 0x80000000, 0x00000010, + 0x00000000, 0x20000010, 0x20000000, 0x00000010, 0x60000000, + 0x00000018, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, + 0x20000000, 0x20000000, 0xa0000000, 0x00000010, 0x80000000, + 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x00000010, + 0x00000000, 0x20000010, 0xa0000000, 0x00000000, 0x20000000, + 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000020, 0x00000001, + 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, + 0xc0000046, 0x4000004b, 0x80000107, 0x00000089, 0x00000014}}, + {2, 53, 0, 65, 0, 28, {0xcc000014, 0x0c000002, 0xc0000010, 0xb400001c, 0x3c000004, + 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0x0c000002, + 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, + 0x0000000c, 0xb8000010, 0x08000018, 0x78000010, 0x08000014, + 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, + 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, + 0xa0000000, 0x00000000, 0x00000000, 0x20000000, 0x80000000, + 0x00000010, 0x00000000, 0x20000010, 0x20000000, 0x00000010, + 0x60000000, 0x00000018, 0xe0000000, 0x90000000, 0x30000010, + 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x00000010, + 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, + 0x00000010, 0x00000000, 0x20000010, 0xa0000000, 0x00000000, + 0x20000000, 0x20000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000020, + 0x00000001, 0x40000002, 0x40000041, 0x40000022, 0x80000005, + 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, 0x00000089}}, + {2, 54, 0, 65, 0, 29, {0x0400001c, 0xcc000014, 0x0c000002, 0xc0000010, 0xb400001c, + 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, + 0x0c000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, + 0xb0000010, 0x0000000c, 0xb8000010, 0x08000018, 0x78000010, + 0x08000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, + 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, + 0x98000010, 0xa0000000, 0x00000000, 0x00000000, 0x20000000, + 0x80000000, 0x00000010, 0x00000000, 0x20000010, 0x20000000, + 0x00000010, 0x60000000, 0x00000018, 0xe0000000, 0x90000000, + 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, + 0x00000010, 0x80000000, 0x20000000, 0x20000000, 0x20000000, + 0x80000000, 0x00000010, 0x00000000, 0x20000010, 0xa0000000, + 0x00000000, 0x20000000, 0x20000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000020, 0x00000001, 0x40000002, 0x40000041, 0x40000022, + 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107}}, + {2, 55, 0, 65, 0, 30, {0x00000010, 0x0400001c, 0xcc000014, 0x0c000002, 0xc0000010, + 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, + 0xec000014, 0x0c000002, 0xc0000010, 0xb400001c, 0x2c000004, + 0xbc000018, 0xb0000010, 0x0000000c, 0xb8000010, 0x08000018, + 0x78000010, 0x08000014, 0x70000010, 0xb800001c, 0xe8000000, + 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, + 0xb8000010, 0x98000010, 0xa0000000, 0x00000000, 0x00000000, + 0x20000000, 0x80000000, 0x00000010, 0x00000000, 0x20000010, + 0x20000000, 0x00000010, 0x60000000, 0x00000018, 0xe0000000, + 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, + 0xa0000000, 0x00000010, 0x80000000, 0x20000000, 0x20000000, + 0x20000000, 0x80000000, 0x00000010, 0x00000000, 0x20000010, + 0xa0000000, 0x00000000, 0x20000000, 0x20000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000020, 0x00000001, 0x40000002, 0x40000041, + 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b}}, + {2, 56, 0, 65, 0, 31, {0x2600001a, 0x00000010, 0x0400001c, 0xcc000014, 0x0c000002, + 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, + 0x2400001c, 0xec000014, 0x0c000002, 0xc0000010, 0xb400001c, + 0x2c000004, 0xbc000018, 0xb0000010, 0x0000000c, 0xb8000010, + 0x08000018, 0x78000010, 0x08000014, 0x70000010, 0xb800001c, + 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, + 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0x00000000, + 0x00000000, 0x20000000, 0x80000000, 0x00000010, 0x00000000, + 0x20000010, 0x20000000, 0x00000010, 0x60000000, 0x00000018, + 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, + 0x20000000, 0xa0000000, 0x00000010, 0x80000000, 0x20000000, + 0x20000000, 0x20000000, 0x80000000, 0x00000010, 0x00000000, + 0x20000010, 0xa0000000, 0x00000000, 0x20000000, 0x20000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000020, 0x00000001, 0x40000002, + 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046}}, + {0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}; +void +ubc_check(const uint32_t W[80], uint32_t dvmask[1]) +{ + uint32_t mask = ~((uint32_t)(0)); + mask &= (((((W[44] ^ W[45]) >> 29) & 1) - 1) | + ~(DV_I_48_0_bit | DV_I_51_0_bit | DV_I_52_0_bit | DV_II_45_0_bit | + DV_II_46_0_bit | DV_II_50_0_bit | DV_II_51_0_bit)); + mask &= (((((W[49] ^ W[50]) >> 29) & 1) - 1) | + ~(DV_I_46_0_bit | DV_II_45_0_bit | DV_II_50_0_bit | DV_II_51_0_bit | + DV_II_55_0_bit | DV_II_56_0_bit)); + mask &= (((((W[48] ^ W[49]) >> 29) & 1) - 1) | + ~(DV_I_45_0_bit | DV_I_52_0_bit | DV_II_49_0_bit | DV_II_50_0_bit | + DV_II_54_0_bit | DV_II_55_0_bit)); + mask &= ((((W[47] ^ (W[50] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | + DV_II_51_0_bit | DV_II_56_0_bit)); + mask &= (((((W[47] ^ W[48]) >> 29) & 1) - 1) | + ~(DV_I_44_0_bit | DV_I_51_0_bit | DV_II_48_0_bit | DV_II_49_0_bit | + DV_II_53_0_bit | DV_II_54_0_bit)); + mask &= (((((W[46] >> 4) ^ (W[49] >> 29)) & 1) - 1) | + ~(DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit | DV_II_50_0_bit | + DV_II_55_0_bit)); + mask &= (((((W[46] ^ W[47]) >> 29) & 1) - 1) | + ~(DV_I_43_0_bit | DV_I_50_0_bit | DV_II_47_0_bit | DV_II_48_0_bit | + DV_II_52_0_bit | DV_II_53_0_bit)); + mask &= (((((W[45] >> 4) ^ (W[48] >> 29)) & 1) - 1) | + ~(DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit | DV_II_49_0_bit | + DV_II_54_0_bit)); + mask &= (((((W[45] ^ W[46]) >> 29) & 1) - 1) | + ~(DV_I_49_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_47_0_bit | + DV_II_51_0_bit | DV_II_52_0_bit)); + mask &= (((((W[44] >> 4) ^ (W[47] >> 29)) & 1) - 1) | + ~(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit | DV_II_48_0_bit | + DV_II_53_0_bit)); + mask &= (((((W[43] >> 4) ^ (W[46] >> 29)) & 1) - 1) | + ~(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit | DV_II_47_0_bit | + DV_II_52_0_bit)); + mask &= (((((W[43] ^ W[44]) >> 29) & 1) - 1) | + ~(DV_I_47_0_bit | DV_I_50_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | + DV_II_49_0_bit | DV_II_50_0_bit)); + mask &= (((((W[42] >> 4) ^ (W[45] >> 29)) & 1) - 1) | + ~(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | + DV_II_51_0_bit)); + mask &= (((((W[41] >> 4) ^ (W[44] >> 29)) & 1) - 1) | + ~(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | + DV_II_50_0_bit)); + mask &= (((((W[40] ^ W[41]) >> 29) & 1) - 1) | + ~(DV_I_44_0_bit | DV_I_47_0_bit | DV_I_48_0_bit | DV_II_46_0_bit | + DV_II_47_0_bit | DV_II_56_0_bit)); + mask &= + (((((W[54] ^ W[55]) >> 29) & 1) - 1) | + ~(DV_I_51_0_bit | DV_II_47_0_bit | DV_II_50_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)); + mask &= + (((((W[53] ^ W[54]) >> 29) & 1) - 1) | + ~(DV_I_50_0_bit | DV_II_46_0_bit | DV_II_49_0_bit | DV_II_54_0_bit | DV_II_55_0_bit)); + mask &= + (((((W[52] ^ W[53]) >> 29) & 1) - 1) | + ~(DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit | DV_II_53_0_bit | DV_II_54_0_bit)); + mask &= + ((((W[50] ^ (W[53] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_50_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_48_0_bit | DV_II_54_0_bit)); + mask &= + (((((W[50] ^ W[51]) >> 29) & 1) - 1) | + ~(DV_I_47_0_bit | DV_II_46_0_bit | DV_II_51_0_bit | DV_II_52_0_bit | DV_II_56_0_bit)); + mask &= + ((((W[49] ^ (W[52] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_47_0_bit | DV_II_53_0_bit)); + mask &= + ((((W[48] ^ (W[51] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_52_0_bit)); + mask &= + (((((W[42] ^ W[43]) >> 29) & 1) - 1) | + ~(DV_I_46_0_bit | DV_I_49_0_bit | DV_I_50_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)); + mask &= + (((((W[41] ^ W[42]) >> 29) & 1) - 1) | + ~(DV_I_45_0_bit | DV_I_48_0_bit | DV_I_49_0_bit | DV_II_47_0_bit | DV_II_48_0_bit)); + mask &= + (((((W[40] >> 4) ^ (W[43] >> 29)) & 1) - 1) | + ~(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_50_0_bit | DV_II_49_0_bit | DV_II_56_0_bit)); + mask &= + (((((W[39] >> 4) ^ (W[42] >> 29)) & 1) - 1) | + ~(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_49_0_bit | DV_II_48_0_bit | DV_II_55_0_bit)); + if (mask & + (DV_I_44_0_bit | DV_I_48_0_bit | DV_II_47_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) + mask &= (((((W[38] >> 4) ^ (W[41] >> 29)) & 1) - 1) | + ~(DV_I_44_0_bit | DV_I_48_0_bit | DV_II_47_0_bit | DV_II_54_0_bit | + DV_II_56_0_bit)); + mask &= + (((((W[37] >> 4) ^ (W[40] >> 29)) & 1) - 1) | + ~(DV_I_43_0_bit | DV_I_47_0_bit | DV_II_46_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)); + if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)) + mask &= (((((W[55] ^ W[56]) >> 29) & 1) - 1) | + ~(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)); + if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_50_0_bit | DV_II_56_0_bit)) + mask &= ((((W[52] ^ (W[55] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_50_0_bit | DV_II_56_0_bit)); + if (mask & (DV_I_51_0_bit | DV_II_47_0_bit | DV_II_49_0_bit | DV_II_55_0_bit)) + mask &= ((((W[51] ^ (W[54] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_51_0_bit | DV_II_47_0_bit | DV_II_49_0_bit | DV_II_55_0_bit)); + if (mask & (DV_I_48_0_bit | DV_II_47_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)) + mask &= (((((W[51] ^ W[52]) >> 29) & 1) - 1) | + ~(DV_I_48_0_bit | DV_II_47_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)); + if (mask & (DV_I_46_0_bit | DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit)) + mask &= (((((W[36] >> 4) ^ (W[40] >> 29)) & 1) - 1) | + ~(DV_I_46_0_bit | DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit)); + if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)) + mask &= ((0 - (((W[53] ^ W[56]) >> 29) & 1)) | + ~(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)); + if (mask & (DV_I_50_0_bit | DV_II_46_0_bit | DV_II_47_0_bit)) + mask &= ((0 - (((W[51] ^ W[54]) >> 29) & 1)) | + ~(DV_I_50_0_bit | DV_II_46_0_bit | DV_II_47_0_bit)); + if (mask & (DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit)) + mask &= ((0 - (((W[50] ^ W[52]) >> 29) & 1)) | + ~(DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit)); + if (mask & (DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit)) + mask &= ((0 - (((W[49] ^ W[51]) >> 29) & 1)) | + ~(DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit)); + if (mask & (DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit)) + mask &= ((0 - (((W[48] ^ W[50]) >> 29) & 1)) | + ~(DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit)); + if (mask & (DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit)) + mask &= ((0 - (((W[47] ^ W[49]) >> 29) & 1)) | + ~(DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit)); + if (mask & (DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit)) + mask &= ((0 - (((W[46] ^ W[48]) >> 29) & 1)) | + ~(DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit)); + mask &= ((((W[45] ^ W[47]) & (1 << 6)) - (1 << 6)) | + ~(DV_I_47_2_bit | DV_I_49_2_bit | DV_I_51_2_bit)); + if (mask & (DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit)) + mask &= ((0 - (((W[45] ^ W[47]) >> 29) & 1)) | + ~(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit)); + mask &= + (((((W[44] ^ W[46]) >> 6) & 1) - 1) | ~(DV_I_46_2_bit | DV_I_48_2_bit | DV_I_50_2_bit)); + if (mask & (DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit)) + mask &= ((0 - (((W[44] ^ W[46]) >> 29) & 1)) | + ~(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit)); + mask &= ((0 - ((W[41] ^ (W[42] >> 5)) & (1 << 1))) | + ~(DV_I_48_2_bit | DV_II_46_2_bit | DV_II_51_2_bit)); + mask &= ((0 - ((W[40] ^ (W[41] >> 5)) & (1 << 1))) | + ~(DV_I_47_2_bit | DV_I_51_2_bit | DV_II_50_2_bit)); + if (mask & (DV_I_44_0_bit | DV_I_46_0_bit | DV_II_56_0_bit)) + mask &= ((0 - (((W[40] ^ W[42]) >> 4) & 1)) | + ~(DV_I_44_0_bit | DV_I_46_0_bit | DV_II_56_0_bit)); + mask &= ((0 - ((W[39] ^ (W[40] >> 5)) & (1 << 1))) | + ~(DV_I_46_2_bit | DV_I_50_2_bit | DV_II_49_2_bit)); + if (mask & (DV_I_43_0_bit | DV_I_45_0_bit | DV_II_55_0_bit)) + mask &= ((0 - (((W[39] ^ W[41]) >> 4) & 1)) | + ~(DV_I_43_0_bit | DV_I_45_0_bit | DV_II_55_0_bit)); + if (mask & (DV_I_44_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) + mask &= ((0 - (((W[38] ^ W[40]) >> 4) & 1)) | + ~(DV_I_44_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)); + if (mask & (DV_I_43_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)) + mask &= ((0 - (((W[37] ^ W[39]) >> 4) & 1)) | + ~(DV_I_43_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)); + mask &= ((0 - ((W[36] ^ (W[37] >> 5)) & (1 << 1))) | + ~(DV_I_47_2_bit | DV_I_50_2_bit | DV_II_46_2_bit)); + if (mask & (DV_I_45_0_bit | DV_I_48_0_bit | DV_II_47_0_bit)) + mask &= (((((W[35] >> 4) ^ (W[39] >> 29)) & 1) - 1) | + ~(DV_I_45_0_bit | DV_I_48_0_bit | DV_II_47_0_bit)); + if (mask & (DV_I_48_0_bit | DV_II_48_0_bit)) + mask &= + ((0 - ((W[63] ^ (W[64] >> 5)) & (1 << 0))) | ~(DV_I_48_0_bit | DV_II_48_0_bit)); + if (mask & (DV_I_45_0_bit | DV_II_45_0_bit)) + mask &= + ((0 - ((W[63] ^ (W[64] >> 5)) & (1 << 1))) | ~(DV_I_45_0_bit | DV_II_45_0_bit)); + if (mask & (DV_I_47_0_bit | DV_II_47_0_bit)) + mask &= + ((0 - ((W[62] ^ (W[63] >> 5)) & (1 << 0))) | ~(DV_I_47_0_bit | DV_II_47_0_bit)); + if (mask & (DV_I_46_0_bit | DV_II_46_0_bit)) + mask &= + ((0 - ((W[61] ^ (W[62] >> 5)) & (1 << 0))) | ~(DV_I_46_0_bit | DV_II_46_0_bit)); + mask &= ((0 - ((W[61] ^ (W[62] >> 5)) & (1 << 2))) | ~(DV_I_46_2_bit | DV_II_46_2_bit)); + if (mask & (DV_I_45_0_bit | DV_II_45_0_bit)) + mask &= + ((0 - ((W[60] ^ (W[61] >> 5)) & (1 << 0))) | ~(DV_I_45_0_bit | DV_II_45_0_bit)); + if (mask & (DV_II_51_0_bit | DV_II_54_0_bit)) + mask &= (((((W[58] ^ W[59]) >> 29) & 1) - 1) | ~(DV_II_51_0_bit | DV_II_54_0_bit)); + if (mask & (DV_II_50_0_bit | DV_II_53_0_bit)) + mask &= (((((W[57] ^ W[58]) >> 29) & 1) - 1) | ~(DV_II_50_0_bit | DV_II_53_0_bit)); + if (mask & (DV_II_52_0_bit | DV_II_54_0_bit)) + mask &= ((((W[56] ^ (W[59] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_II_52_0_bit | DV_II_54_0_bit)); + if (mask & (DV_II_51_0_bit | DV_II_52_0_bit)) + mask &= ((0 - (((W[56] ^ W[59]) >> 29) & 1)) | ~(DV_II_51_0_bit | DV_II_52_0_bit)); + if (mask & (DV_II_49_0_bit | DV_II_52_0_bit)) + mask &= (((((W[56] ^ W[57]) >> 29) & 1) - 1) | ~(DV_II_49_0_bit | DV_II_52_0_bit)); + if (mask & (DV_II_51_0_bit | DV_II_53_0_bit)) + mask &= ((((W[55] ^ (W[58] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_II_51_0_bit | DV_II_53_0_bit)); + if (mask & (DV_II_50_0_bit | DV_II_52_0_bit)) + mask &= ((((W[54] ^ (W[57] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_II_50_0_bit | DV_II_52_0_bit)); + if (mask & (DV_II_49_0_bit | DV_II_51_0_bit)) + mask &= ((((W[53] ^ (W[56] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_II_49_0_bit | DV_II_51_0_bit)); + mask &= + ((((W[51] ^ (W[50] >> 5)) & (1 << 1)) - (1 << 1)) | ~(DV_I_50_2_bit | DV_II_46_2_bit)); + mask &= ((((W[48] ^ W[50]) & (1 << 6)) - (1 << 6)) | ~(DV_I_50_2_bit | DV_II_46_2_bit)); + if (mask & (DV_I_51_0_bit | DV_I_52_0_bit)) + mask &= ((0 - (((W[48] ^ W[55]) >> 29) & 1)) | ~(DV_I_51_0_bit | DV_I_52_0_bit)); + mask &= ((((W[47] ^ W[49]) & (1 << 6)) - (1 << 6)) | ~(DV_I_49_2_bit | DV_I_51_2_bit)); + mask &= + ((((W[48] ^ (W[47] >> 5)) & (1 << 1)) - (1 << 1)) | ~(DV_I_47_2_bit | DV_II_51_2_bit)); + mask &= ((((W[46] ^ W[48]) & (1 << 6)) - (1 << 6)) | ~(DV_I_48_2_bit | DV_I_50_2_bit)); + mask &= + ((((W[47] ^ (W[46] >> 5)) & (1 << 1)) - (1 << 1)) | ~(DV_I_46_2_bit | DV_II_50_2_bit)); + mask &= ((0 - ((W[44] ^ (W[45] >> 5)) & (1 << 1))) | ~(DV_I_51_2_bit | DV_II_49_2_bit)); + mask &= ((((W[43] ^ W[45]) & (1 << 6)) - (1 << 6)) | ~(DV_I_47_2_bit | DV_I_49_2_bit)); + mask &= (((((W[42] ^ W[44]) >> 6) & 1) - 1) | ~(DV_I_46_2_bit | DV_I_48_2_bit)); + mask &= + ((((W[43] ^ (W[42] >> 5)) & (1 << 1)) - (1 << 1)) | ~(DV_II_46_2_bit | DV_II_51_2_bit)); + mask &= + ((((W[42] ^ (W[41] >> 5)) & (1 << 1)) - (1 << 1)) | ~(DV_I_51_2_bit | DV_II_50_2_bit)); + mask &= + ((((W[41] ^ (W[40] >> 5)) & (1 << 1)) - (1 << 1)) | ~(DV_I_50_2_bit | DV_II_49_2_bit)); + if (mask & (DV_I_52_0_bit | DV_II_51_0_bit)) + mask &= ((((W[39] ^ (W[43] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_52_0_bit | DV_II_51_0_bit)); + if (mask & (DV_I_51_0_bit | DV_II_50_0_bit)) + mask &= ((((W[38] ^ (W[42] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_51_0_bit | DV_II_50_0_bit)); + if (mask & (DV_I_48_2_bit | DV_I_51_2_bit)) + mask &= ((0 - ((W[37] ^ (W[38] >> 5)) & (1 << 1))) | ~(DV_I_48_2_bit | DV_I_51_2_bit)); + if (mask & (DV_I_50_0_bit | DV_II_49_0_bit)) + mask &= ((((W[37] ^ (W[41] >> 25)) & (1 << 4)) - (1 << 4)) | + ~(DV_I_50_0_bit | DV_II_49_0_bit)); + if (mask & (DV_II_52_0_bit | DV_II_54_0_bit)) + mask &= ((0 - ((W[36] ^ W[38]) & (1 << 4))) | ~(DV_II_52_0_bit | DV_II_54_0_bit)); + mask &= ((0 - ((W[35] ^ (W[36] >> 5)) & (1 << 1))) | ~(DV_I_46_2_bit | DV_I_49_2_bit)); + if (mask & (DV_I_51_0_bit | DV_II_47_0_bit)) + mask &= ((((W[35] ^ (W[39] >> 25)) & (1 << 3)) - (1 << 3)) | + ~(DV_I_51_0_bit | DV_II_47_0_bit)); + if (mask) { + if (mask & DV_I_43_0_bit) + if (!((W[61] ^ (W[62] >> 5)) & (1 << 1)) || + !(!((W[59] ^ (W[63] >> 25)) & (1 << 5))) || + !((W[58] ^ (W[63] >> 30)) & (1 << 0))) + mask &= ~DV_I_43_0_bit; + if (mask & DV_I_44_0_bit) + if (!((W[62] ^ (W[63] >> 5)) & (1 << 1)) || + !(!((W[60] ^ (W[64] >> 25)) & (1 << 5))) || + !((W[59] ^ (W[64] >> 30)) & (1 << 0))) + mask &= ~DV_I_44_0_bit; + if (mask & DV_I_46_2_bit) + mask &= ((~((W[40] ^ W[42]) >> 2)) | ~DV_I_46_2_bit); + if (mask & DV_I_47_2_bit) + if (!((W[62] ^ (W[63] >> 5)) & (1 << 2)) || !(!((W[41] ^ W[43]) & (1 << 6)))) + mask &= ~DV_I_47_2_bit; + if (mask & DV_I_48_2_bit) + if (!((W[63] ^ (W[64] >> 5)) & (1 << 2)) || + !(!((W[48] ^ (W[49] << 5)) & (1 << 6)))) + mask &= ~DV_I_48_2_bit; + if (mask & DV_I_49_2_bit) + if (!(!((W[49] ^ (W[50] << 5)) & (1 << 6))) || !((W[42] ^ W[50]) & (1 << 1)) || + !(!((W[39] ^ (W[40] << 5)) & (1 << 6))) || !((W[38] ^ W[40]) & (1 << 1))) + mask &= ~DV_I_49_2_bit; + if (mask & DV_I_50_0_bit) + mask &= ((((W[36] ^ W[37]) << 7)) | ~DV_I_50_0_bit); + if (mask & DV_I_50_2_bit) + mask &= ((((W[43] ^ W[51]) << 11)) | ~DV_I_50_2_bit); + if (mask & DV_I_51_0_bit) + mask &= ((((W[37] ^ W[38]) << 9)) | ~DV_I_51_0_bit); + if (mask & DV_I_51_2_bit) + if (!(!((W[51] ^ (W[52] << 5)) & (1 << 6))) || !(!((W[49] ^ W[51]) & (1 << 6))) || + !(!((W[37] ^ (W[37] >> 5)) & (1 << 1))) || + !(!((W[35] ^ (W[39] >> 25)) & (1 << 5)))) + mask &= ~DV_I_51_2_bit; + if (mask & DV_I_52_0_bit) + mask &= ((((W[38] ^ W[39]) << 11)) | ~DV_I_52_0_bit); + if (mask & DV_II_46_2_bit) + mask &= ((((W[47] ^ W[51]) << 17)) | ~DV_II_46_2_bit); + if (mask & DV_II_48_0_bit) + if (!(!((W[36] ^ (W[40] >> 25)) & (1 << 3))) || + !((W[35] ^ (W[40] << 2)) & (1 << 30))) + mask &= ~DV_II_48_0_bit; + if (mask & DV_II_49_0_bit) + if (!(!((W[37] ^ (W[41] >> 25)) & (1 << 3))) || + !((W[36] ^ (W[41] << 2)) & (1 << 30))) + mask &= ~DV_II_49_0_bit; + if (mask & DV_II_49_2_bit) + if (!(!((W[53] ^ (W[54] << 5)) & (1 << 6))) || !(!((W[51] ^ W[53]) & (1 << 6))) || + !((W[50] ^ W[54]) & (1 << 1)) || !(!((W[45] ^ (W[46] << 5)) & (1 << 6))) || + !(!((W[37] ^ (W[41] >> 25)) & (1 << 5))) || + !((W[36] ^ (W[41] >> 30)) & (1 << 0))) + mask &= ~DV_II_49_2_bit; + if (mask & DV_II_50_0_bit) + if (!((W[55] ^ W[58]) & (1 << 29)) || !(!((W[38] ^ (W[42] >> 25)) & (1 << 3))) || + !((W[37] ^ (W[42] << 2)) & (1 << 30))) + mask &= ~DV_II_50_0_bit; + if (mask & DV_II_50_2_bit) + if (!(!((W[54] ^ (W[55] << 5)) & (1 << 6))) || !(!((W[52] ^ W[54]) & (1 << 6))) || + !((W[51] ^ W[55]) & (1 << 1)) || !((W[45] ^ W[47]) & (1 << 1)) || + !(!((W[38] ^ (W[42] >> 25)) & (1 << 5))) || + !((W[37] ^ (W[42] >> 30)) & (1 << 0))) + mask &= ~DV_II_50_2_bit; + if (mask & DV_II_51_0_bit) + if (!(!((W[39] ^ (W[43] >> 25)) & (1 << 3))) || + !((W[38] ^ (W[43] << 2)) & (1 << 30))) + mask &= ~DV_II_51_0_bit; + if (mask & DV_II_51_2_bit) + if (!(!((W[55] ^ (W[56] << 5)) & (1 << 6))) || !(!((W[53] ^ W[55]) & (1 << 6))) || + !((W[52] ^ W[56]) & (1 << 1)) || !((W[46] ^ W[48]) & (1 << 1)) || + !(!((W[39] ^ (W[43] >> 25)) & (1 << 5))) || + !((W[38] ^ (W[43] >> 30)) & (1 << 0))) + mask &= ~DV_II_51_2_bit; + if (mask & DV_II_52_0_bit) + if (!(!((W[59] ^ W[60]) & (1 << 29))) || + !(!((W[40] ^ (W[44] >> 25)) & (1 << 3))) || + !(!((W[40] ^ (W[44] >> 25)) & (1 << 4))) || + !((W[39] ^ (W[44] << 2)) & (1 << 30))) + mask &= ~DV_II_52_0_bit; + if (mask & DV_II_53_0_bit) + if (!((W[58] ^ W[61]) & (1 << 29)) || !(!((W[57] ^ (W[61] >> 25)) & (1 << 4))) || + !(!((W[41] ^ (W[45] >> 25)) & (1 << 3))) || + !(!((W[41] ^ (W[45] >> 25)) & (1 << 4)))) + mask &= ~DV_II_53_0_bit; + if (mask & DV_II_54_0_bit) + if (!(!((W[58] ^ (W[62] >> 25)) & (1 << 4))) || + !(!((W[42] ^ (W[46] >> 25)) & (1 << 3))) || + !(!((W[42] ^ (W[46] >> 25)) & (1 << 4)))) + mask &= ~DV_II_54_0_bit; + if (mask & DV_II_55_0_bit) + if (!(!((W[59] ^ (W[63] >> 25)) & (1 << 4))) || + !(!((W[57] ^ (W[59] >> 25)) & (1 << 4))) || + !(!((W[43] ^ (W[47] >> 25)) & (1 << 3))) || + !(!((W[43] ^ (W[47] >> 25)) & (1 << 4)))) + mask &= ~DV_II_55_0_bit; + if (mask & DV_II_56_0_bit) + if (!(!((W[60] ^ (W[64] >> 25)) & (1 << 4))) || + !(!((W[44] ^ (W[48] >> 25)) & (1 << 3))) || + !(!((W[44] ^ (W[48] >> 25)) & (1 << 4)))) + mask &= ~DV_II_56_0_bit; + } + + dvmask[0] = mask; +} + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sha1cd/ubc_check.h 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,62 @@ +/*** + * Copyright 2017 Marc Stevens , Dan Shumow + * Distributed under the MIT Software License. + * See accompanying file LICENSE.txt or copy at + * https://opensource.org/licenses/MIT + ***/ + +/* +// this file was generated by the 'parse_bitrel' program in the tools section +// using the data files from directory 'tools/data/3565' +// +// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check +// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) +// dm[80] is the expanded message block XOR-difference defined by the DV +// testt is the step to do the recompression from for collision detection +// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check +// +// ubc_check takes as input an expanded message block and verifies the unavoidable +bitconditions for all listed DVs +// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions +for that DV have been met +// thus one needs to do the recompression check for each DV that has its bit set +*/ + +#ifndef SHA1DC_UBC_CHECK_H +#define SHA1DC_UBC_CHECK_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#endif + +#define DVMASKSIZE 1 +typedef struct { + int dvType; + int dvK; + int dvB; + int testt; + int maski; + int maskb; + uint32_t dm[80]; +} dv_info_t; +extern dv_info_t sha1_dvs[]; +void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]); + +#define DOSTORESTATE58 +#define DOSTORESTATE65 + +#define CHECK_DVMASK(_DVMASK) (0 != _DVMASK[0]) + +#if defined(__cplusplus) +} +#endif + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H +#endif + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/signatures.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/signatures.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/signatures.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/signatures.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -29,6 +29,7 @@ #include "librepgp/stream-packet.h" #include "librepgp/stream-sig.h" #include "utils.h" +#include "sec_profile.hpp" /** * @brief Add signature fields to the hash context and finish it. @@ -39,105 +40,92 @@ * @param hlen on success will be filled with the hash size, otherwise zeroed * @return RNP_SUCCESS on success or some error otherwise */ -static rnp_result_t -signature_hash_finish(const pgp_signature_t *sig, - pgp_hash_t * hash, - uint8_t * hbuf, - size_t * hlen) +static void +signature_hash_finish(const pgp_signature_t &sig, rnp::Hash &hash, uint8_t *hbuf, size_t &hlen) { - if (!hash || !sig || !hbuf || !hlen) { - return RNP_ERROR_NULL_POINTER; - } - if (pgp_hash_add(hash, sig->hashed_data, sig->hashed_len)) { - RNP_LOG("failed to hash sig"); - goto error; - } - if (sig->version > PGP_V3) { + hash.add(sig.hashed_data, sig.hashed_len); + if (sig.version > PGP_V3) { uint8_t trailer[6] = {0x04, 0xff, 0x00, 0x00, 0x00, 0x00}; - STORE32BE(&trailer[2], sig->hashed_len); - - if (pgp_hash_add(hash, trailer, 6)) { - RNP_LOG("failed to add sig trailer"); - goto error; - } + STORE32BE(&trailer[2], sig.hashed_len); + hash.add(trailer, 6); } - - *hlen = pgp_hash_finish(hash, hbuf); - return RNP_SUCCESS; -error: - pgp_hash_finish(hash, NULL); - return RNP_ERROR_GENERIC; + hlen = hash.finish(hbuf); } -rnp_result_t -signature_init(const pgp_key_material_t *key, pgp_hash_alg_t hash_alg, pgp_hash_t *hash) +void +signature_init(const pgp_key_material_t &key, pgp_hash_alg_t hash_alg, rnp::Hash &hash) { - if (!pgp_hash_create(hash, hash_alg)) { - return RNP_ERROR_GENERIC; - } - - if (key->alg == PGP_PKA_SM2) { - rnp_result_t r = sm2_compute_za(&key->ec, hash); + hash = rnp::Hash(hash_alg); + if (key.alg == PGP_PKA_SM2) { +#if defined(ENABLE_SM2) + rnp_result_t r = sm2_compute_za(key.ec, hash); if (r != RNP_SUCCESS) { - pgp_hash_finish(hash, NULL); RNP_LOG("failed to compute SM2 ZA field"); - return r; + throw rnp::rnp_exception(r); } +#else + RNP_LOG("SM2 ZA computation not available"); + throw rnp::rnp_exception(RNP_ERROR_NOT_IMPLEMENTED); +#endif } - return RNP_SUCCESS; } -rnp_result_t -signature_calculate(pgp_signature_t * sig, - const pgp_key_material_t *seckey, - pgp_hash_t * hash, - rng_t * rng) +void +signature_calculate(pgp_signature_t & sig, + pgp_key_material_t & seckey, + rnp::Hash & hash, + rnp::SecurityContext &ctx) { uint8_t hval[PGP_MAX_HASH_SIZE]; size_t hlen = 0; rnp_result_t ret = RNP_ERROR_GENERIC; - const pgp_hash_alg_t hash_alg = pgp_hash_alg_type(hash); + const pgp_hash_alg_t hash_alg = hash.alg(); /* Finalize hash first, since function is required to do this */ - - ret = signature_hash_finish(sig, hash, hval, &hlen); - if (ret != RNP_SUCCESS) { - return ret; + try { + signature_hash_finish(sig, hash, hval, hlen); + } catch (const std::exception &e) { + RNP_LOG("Failed to finalize hash: %s", e.what()); + throw; } - if (!seckey) { - return RNP_ERROR_NULL_POINTER; - } - if (!seckey->secret) { - return RNP_ERROR_BAD_PARAMETERS; - } - if (sig->palg != seckey->alg) { - RNP_LOG("Signature and secret key do not agree on algorithm type"); - return RNP_ERROR_BAD_PARAMETERS; + if (!seckey.secret) { + RNP_LOG("Secret key is required."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + if (sig.palg != seckey.alg) { + RNP_LOG("Signature and secret key do not agree on algorithm type."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + /* Validate key material if didn't before */ + seckey.validate(ctx, false); + if (!seckey.valid()) { + RNP_LOG("Attempt to sign with invalid key material."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } /* copy left 16 bits to signature */ - memcpy(sig->lbits, hval, 2); + memcpy(sig.lbits, hval, 2); /* sign */ pgp_signature_material_t material = {}; - switch (sig->palg) { + switch (sig.palg) { case PGP_PKA_RSA: case PGP_PKA_RSA_ENCRYPT_ONLY: case PGP_PKA_RSA_SIGN_ONLY: - ret = rsa_sign_pkcs1(rng, &material.rsa, sig->halg, hval, hlen, &seckey->rsa); + ret = rsa_sign_pkcs1(&ctx.rng, &material.rsa, sig.halg, hval, hlen, &seckey.rsa); if (ret) { RNP_LOG("rsa signing failed"); } break; case PGP_PKA_EDDSA: - ret = eddsa_sign(rng, &material.ecc, hval, hlen, &seckey->ec); + ret = eddsa_sign(&ctx.rng, &material.ecc, hval, hlen, &seckey.ec); if (ret) { RNP_LOG("eddsa signing failed"); } break; case PGP_PKA_DSA: - ret = dsa_sign(rng, &material.dsa, hval, hlen, &seckey->dsa); + ret = dsa_sign(&ctx.rng, &material.dsa, hval, hlen, &seckey.dsa); if (ret != RNP_SUCCESS) { RNP_LOG("DSA signing failed"); } @@ -149,13 +137,17 @@ case PGP_PKA_ECDH: case PGP_PKA_ECDSA: case PGP_PKA_SM2: { - const ec_curve_desc_t *curve = get_curve_desc(seckey->ec.curve); - + const ec_curve_desc_t *curve = get_curve_desc(seckey.ec.curve); if (!curve) { RNP_LOG("Unknown curve"); ret = RNP_ERROR_BAD_PARAMETERS; break; } + if (!curve_supported(seckey.ec.curve)) { + RNP_LOG("EC sign: curve %s is not supported.", curve->pgp_name); + ret = RNP_ERROR_NOT_SUPPORTED; + break; + } /* "-2" because ECDSA on P-521 must work with SHA-512 digest */ if (BITS_TO_BYTES(curve->bitlen) - 2 > hlen) { RNP_LOG("Message hash too small"); @@ -163,33 +155,37 @@ break; } - if (sig->palg == PGP_PKA_SM2) { - ret = sm2_sign(rng, &material.ecc, hash_alg, hval, hlen, &seckey->ec); + if (sig.palg == PGP_PKA_SM2) { +#if defined(ENABLE_SM2) + ret = sm2_sign(&ctx.rng, &material.ecc, hash_alg, hval, hlen, &seckey.ec); if (ret) { RNP_LOG("SM2 signing failed"); } - } else { - ret = ecdsa_sign(rng, &material.ecc, hash_alg, hval, hlen, &seckey->ec); - if (ret) { - RNP_LOG("ECDSA signing failed"); - break; - } +#else + RNP_LOG("SM2 signing is not available."); + ret = RNP_ERROR_NOT_IMPLEMENTED; +#endif + break; + } + + ret = ecdsa_sign(&ctx.rng, &material.ecc, hash_alg, hval, hlen, &seckey.ec); + if (ret) { + RNP_LOG("ECDSA signing failed"); } break; } default: - RNP_LOG("Unsupported algorithm %d", sig->palg); + RNP_LOG("Unsupported algorithm %d", sig.palg); break; } if (ret) { - return ret; + throw rnp::rnp_exception(ret); } try { - sig->write_material(material); - return RNP_SUCCESS; + sig.write_material(material); } catch (const std::exception &e) { RNP_LOG("%s", e.what()); - return RNP_ERROR_GENERIC; + throw; } } @@ -247,73 +243,87 @@ } rnp_result_t -signature_validate(const pgp_signature_t *sig, const pgp_key_material_t *key, pgp_hash_t *hash) +signature_validate(const pgp_signature_t & sig, + const pgp_key_material_t & key, + rnp::Hash & hash, + const rnp::SecurityContext &ctx) { - uint8_t hval[PGP_MAX_HASH_SIZE]; - size_t hlen = 0; - rnp_result_t ret = RNP_ERROR_GENERIC; - - const pgp_hash_alg_t hash_alg = pgp_hash_alg_type(hash); - if (!is_hash_alg_allowed_in_sig(hash_alg)) { + if (!is_hash_alg_allowed_in_sig(hash.alg())) { return RNP_ERROR_SIGNATURE_INVALID; } - if (!key) { - return RNP_ERROR_NULL_POINTER; - } - - if (!is_pubkey_alg_allowed_in_sig(sig->palg)) { + if (!is_pubkey_alg_allowed_in_sig(sig.palg)) { return RNP_ERROR_SIGNATURE_INVALID; } - if (sig->palg != key->alg) { + if (sig.palg != key.alg) { RNP_LOG("Signature and key do not agree on algorithm type: %d vs %d", - (int) sig->palg, - (int) key->alg); + (int) sig.palg, + (int) key.alg); return RNP_ERROR_BAD_PARAMETERS; } + /* Check signature security */ + if (ctx.profile.hash_level(sig.halg, sig.creation()) < rnp::SecurityLevel::Default) { + RNP_LOG("Insecure hash algorithm %d, marking signature as invalid.", sig.halg); + return RNP_ERROR_SIGNATURE_INVALID; + } + /* Finalize hash */ - ret = signature_hash_finish(sig, hash, hval, &hlen); - if (ret != RNP_SUCCESS) { - return ret; + uint8_t hval[PGP_MAX_HASH_SIZE]; + size_t hlen = 0; + try { + signature_hash_finish(sig, hash, hval, hlen); + } catch (const std::exception &e) { + RNP_LOG("Failed to finalize signature hash."); + return RNP_ERROR_GENERIC; } /* compare lbits */ - if (memcmp(hval, sig->lbits, 2)) { + if (memcmp(hval, sig.lbits, 2)) { RNP_LOG("wrong lbits"); return RNP_ERROR_SIGNATURE_INVALID; } /* validate signature */ - pgp_signature_material_t material = {}; try { - sig->parse_material(material); + sig.parse_material(material); } catch (const std::exception &e) { RNP_LOG("%s", e.what()); return RNP_ERROR_OUT_OF_MEMORY; } - switch (sig->palg) { + rnp_result_t ret = RNP_ERROR_GENERIC; + switch (sig.palg) { case PGP_PKA_DSA: - ret = dsa_verify(&material.dsa, hval, hlen, &key->dsa); + ret = dsa_verify(&material.dsa, hval, hlen, &key.dsa); break; case PGP_PKA_EDDSA: - ret = eddsa_verify(&material.ecc, hval, hlen, &key->ec); + ret = eddsa_verify(&material.ecc, hval, hlen, &key.ec); break; case PGP_PKA_SM2: - ret = sm2_verify(&material.ecc, hash_alg, hval, hlen, &key->ec); +#if defined(ENABLE_SM2) + ret = sm2_verify(&material.ecc, hash.alg(), hval, hlen, &key.ec); +#else + RNP_LOG("SM2 verification is not available."); + ret = RNP_ERROR_NOT_IMPLEMENTED; +#endif break; case PGP_PKA_RSA: case PGP_PKA_RSA_SIGN_ONLY: - ret = rsa_verify_pkcs1(&material.rsa, sig->halg, hval, hlen, &key->rsa); + ret = rsa_verify_pkcs1(&material.rsa, sig.halg, hval, hlen, &key.rsa); break; case PGP_PKA_RSA_ENCRYPT_ONLY: RNP_LOG("RSA encrypt-only signature considered as invalid."); ret = RNP_ERROR_SIGNATURE_INVALID; break; case PGP_PKA_ECDSA: - ret = ecdsa_verify(&material.ecc, hash_alg, hval, hlen, &key->ec); + if (!curve_supported(key.ec.curve)) { + RNP_LOG("ECDSA verify: curve %d is not supported.", (int) key.ec.curve); + ret = RNP_ERROR_NOT_SUPPORTED; + break; + } + ret = ecdsa_verify(&material.ecc, hash.alg(), hval, hlen, &key.ec); break; case PGP_PKA_ELGAMAL: case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/signatures.cpp.orig thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/signatures.cpp.orig --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/signatures.cpp.orig 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/signatures.cpp.orig 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2018, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "crypto/signatures.h" +#include "librepgp/stream-packet.h" +#include "librepgp/stream-sig.h" +#include "utils.h" +#include "sec_profile.hpp" + +/** + * @brief Add signature fields to the hash context and finish it. + * @param hash initialized hash context fed with signed data (document, key, etc). + * It is finalized in this function. + * @param sig populated or loaded signature + * @param hbuf buffer to store the resulting hash. Must be large enough for hash output. + * @param hlen on success will be filled with the hash size, otherwise zeroed + * @return RNP_SUCCESS on success or some error otherwise + */ +static void +signature_hash_finish(const pgp_signature_t &sig, rnp::Hash &hash, uint8_t *hbuf, size_t &hlen) +{ + hash.add(sig.hashed_data, sig.hashed_len); + if (sig.version > PGP_V3) { + uint8_t trailer[6] = {0x04, 0xff, 0x00, 0x00, 0x00, 0x00}; + STORE32BE(&trailer[2], sig.hashed_len); + hash.add(trailer, 6); + } + hlen = hash.finish(hbuf); +} + +void +signature_init(const pgp_key_material_t &key, pgp_hash_alg_t hash_alg, rnp::Hash &hash) +{ + hash = rnp::Hash(hash_alg); + if (key.alg == PGP_PKA_SM2) { +#if defined(ENABLE_SM2) + rnp_result_t r = sm2_compute_za(key.ec, hash); + if (r != RNP_SUCCESS) { + RNP_LOG("failed to compute SM2 ZA field"); + throw rnp::rnp_exception(r); + } +#else + RNP_LOG("SM2 ZA computation not available"); + throw rnp::rnp_exception(RNP_ERROR_NOT_IMPLEMENTED); +#endif + } +} + +void +signature_calculate(pgp_signature_t & sig, + pgp_key_material_t & seckey, + rnp::Hash & hash, + rnp::SecurityContext &ctx) +{ + uint8_t hval[PGP_MAX_HASH_SIZE]; + size_t hlen = 0; + rnp_result_t ret = RNP_ERROR_GENERIC; + const pgp_hash_alg_t hash_alg = hash.alg(); + + /* Finalize hash first, since function is required to do this */ + try { + signature_hash_finish(sig, hash, hval, hlen); + } catch (const std::exception &e) { + RNP_LOG("Failed to finalize hash: %s", e.what()); + throw; + } + + if (!seckey.secret) { + RNP_LOG("Secret key is required."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + if (sig.palg != seckey.alg) { + RNP_LOG("Signature and secret key do not agree on algorithm type."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + /* Validate key material if didn't before */ + seckey.validate(ctx, false); + if (!seckey.valid()) { + RNP_LOG("Attempt to sign with invalid key material."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + + /* copy left 16 bits to signature */ + memcpy(sig.lbits, hval, 2); + + /* sign */ + pgp_signature_material_t material = {}; + switch (sig.palg) { + case PGP_PKA_RSA: + case PGP_PKA_RSA_ENCRYPT_ONLY: + case PGP_PKA_RSA_SIGN_ONLY: + ret = rsa_sign_pkcs1(&ctx.rng, &material.rsa, sig.halg, hval, hlen, &seckey.rsa); + if (ret) { + RNP_LOG("rsa signing failed"); + } + break; + case PGP_PKA_EDDSA: + ret = eddsa_sign(&ctx.rng, &material.ecc, hval, hlen, &seckey.ec); + if (ret) { + RNP_LOG("eddsa signing failed"); + } + break; + case PGP_PKA_DSA: + ret = dsa_sign(&ctx.rng, &material.dsa, hval, hlen, &seckey.dsa); + if (ret != RNP_SUCCESS) { + RNP_LOG("DSA signing failed"); + } + break; + /* + * ECDH is signed with ECDSA. This must be changed when ECDH will support + * X25519, but I need to check how it should be done exactly. + */ + case PGP_PKA_ECDH: + case PGP_PKA_ECDSA: + case PGP_PKA_SM2: { + const ec_curve_desc_t *curve = get_curve_desc(seckey.ec.curve); + if (!curve) { + RNP_LOG("Unknown curve"); + ret = RNP_ERROR_BAD_PARAMETERS; + break; + } + if (!curve_supported(seckey.ec.curve)) { + RNP_LOG("EC sign: curve %s is not supported.", curve->pgp_name); + ret = RNP_ERROR_NOT_SUPPORTED; + break; + } + /* "-2" because ECDSA on P-521 must work with SHA-512 digest */ + if (BITS_TO_BYTES(curve->bitlen) - 2 > hlen) { + RNP_LOG("Message hash too small"); + ret = RNP_ERROR_BAD_PARAMETERS; + break; + } + + if (sig.palg == PGP_PKA_SM2) { +#if defined(ENABLE_SM2) + ret = sm2_sign(&ctx.rng, &material.ecc, hash_alg, hval, hlen, &seckey.ec); + if (ret) { + RNP_LOG("SM2 signing failed"); + } +#else + RNP_LOG("SM2 signing is not available."); + ret = RNP_ERROR_NOT_IMPLEMENTED; +#endif + break; + } + + ret = ecdsa_sign(&ctx.rng, &material.ecc, hash_alg, hval, hlen, &seckey.ec); + if (ret) { + RNP_LOG("ECDSA signing failed"); + } + break; + } + default: + RNP_LOG("Unsupported algorithm %d", sig.palg); + break; + } + if (ret) { + throw rnp::rnp_exception(ret); + } + try { + sig.write_material(material); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + throw; + } +} + +rnp_result_t +signature_validate(const pgp_signature_t & sig, + const pgp_key_material_t & key, + rnp::Hash & hash, + const rnp::SecurityContext &ctx) +{ + if (sig.palg != key.alg) { + RNP_LOG("Signature and key do not agree on algorithm type: %d vs %d", + (int) sig.palg, + (int) key.alg); + return RNP_ERROR_BAD_PARAMETERS; + } + + /* Check signature security */ + if (ctx.profile.hash_level(sig.halg, sig.creation()) < rnp::SecurityLevel::Default) { + RNP_LOG("Insecure hash algorithm %d, marking signature as invalid.", sig.halg); + return RNP_ERROR_SIGNATURE_INVALID; + } + + /* Finalize hash */ + uint8_t hval[PGP_MAX_HASH_SIZE]; + size_t hlen = 0; + try { + signature_hash_finish(sig, hash, hval, hlen); + } catch (const std::exception &e) { + RNP_LOG("Failed to finalize signature hash."); + return RNP_ERROR_GENERIC; + } + + /* compare lbits */ + if (memcmp(hval, sig.lbits, 2)) { + RNP_LOG("wrong lbits"); + return RNP_ERROR_SIGNATURE_INVALID; + } + + /* validate signature */ + pgp_signature_material_t material = {}; + try { + sig.parse_material(material); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_OUT_OF_MEMORY; + } + rnp_result_t ret = RNP_ERROR_GENERIC; + switch (sig.palg) { + case PGP_PKA_DSA: + ret = dsa_verify(&material.dsa, hval, hlen, &key.dsa); + break; + case PGP_PKA_EDDSA: + ret = eddsa_verify(&material.ecc, hval, hlen, &key.ec); + break; + case PGP_PKA_SM2: +#if defined(ENABLE_SM2) + ret = sm2_verify(&material.ecc, hash.alg(), hval, hlen, &key.ec); +#else + RNP_LOG("SM2 verification is not available."); + ret = RNP_ERROR_NOT_IMPLEMENTED; +#endif + break; + case PGP_PKA_RSA: + case PGP_PKA_RSA_SIGN_ONLY: + ret = rsa_verify_pkcs1(&material.rsa, sig.halg, hval, hlen, &key.rsa); + break; + case PGP_PKA_RSA_ENCRYPT_ONLY: + RNP_LOG("RSA encrypt-only signature considered as invalid."); + ret = RNP_ERROR_SIGNATURE_INVALID; + break; + case PGP_PKA_ECDSA: + if (!curve_supported(key.ec.curve)) { + RNP_LOG("ECDSA verify: curve %d is not supported.", (int) key.ec.curve); + ret = RNP_ERROR_NOT_SUPPORTED; + break; + } + ret = ecdsa_verify(&material.ecc, hash.alg(), hval, hlen, &key.ec); + break; + case PGP_PKA_ELGAMAL: + case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: + RNP_LOG("ElGamal are considered as invalid."); + ret = RNP_ERROR_SIGNATURE_INVALID; + break; + default: + RNP_LOG("Unknown algorithm"); + ret = RNP_ERROR_BAD_PARAMETERS; + } + return ret; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/signatures.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/signatures.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/signatures.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/signatures.h 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2018-2021, [Ribose Inc](https://www.ribose.com). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,14 +31,12 @@ #include "crypto/hash.h" /** - * Initialize a signature computation. + * @brief Initialize a signature computation. * @param key the key that will be used to sign or verify * @param hash_alg the digest algo to be used - * @param hash digest context that will be initialized + * @param hash digest object that will be initialized */ -rnp_result_t signature_init(const pgp_key_material_t *key, - pgp_hash_alg_t hash_alg, - pgp_hash_t * hash); +void signature_init(const pgp_key_material_t &key, pgp_hash_alg_t hash_alg, rnp::Hash &hash); /** * @brief Calculate signature with pre-populated hash @@ -47,12 +45,11 @@ * @param hash pre-populated with signed data hash context. It is finalized and destroyed * during the execution. Signature fields and trailer are hashed in this function. * @param rng random number generator - * @return RNP_SUCCESS if signature was successfully calculated or error code otherwise */ -rnp_result_t signature_calculate(pgp_signature_t * sig, - const pgp_key_material_t *seckey, - pgp_hash_t * hash, - rng_t * rng); +void signature_calculate(pgp_signature_t & sig, + pgp_key_material_t & seckey, + rnp::Hash & hash, + rnp::SecurityContext &ctx); /** * @brief Validate a signature with pre-populated hash. This method just checks correspondence @@ -60,12 +57,13 @@ * checked for validity. * @param sig signature to validate * @param key public key material of the verifying key - * @param hash pre-populated with signed data hash context. It is finalized and destroyed + * @param hash pre-populated with signed data hash context. It is finalized * during the execution. Signature fields and trailer are hashed in this function. * @return RNP_SUCCESS if signature was successfully validated or error code otherwise. */ -rnp_result_t signature_validate(const pgp_signature_t * sig, - const pgp_key_material_t *key, - pgp_hash_t * hash); +rnp_result_t signature_validate(const pgp_signature_t & sig, + const pgp_key_material_t & key, + rnp::Hash & hash, + const rnp::SecurityContext &ctx); #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sm2.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sm2.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sm2.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sm2.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -29,6 +29,7 @@ #include "sm2.h" #include "hash.h" #include "utils.h" +#include "bn.h" static bool sm2_load_public_key(botan_pubkey_t *pubkey, const pgp_ec_key_t *keydata) @@ -80,26 +81,21 @@ } rnp_result_t -sm2_compute_za(const pgp_ec_key_t *key, pgp_hash_t *hash, const char *ident_field) +sm2_compute_za(const pgp_ec_key_t &key, rnp::Hash &hash, const char *ident_field) { - uint8_t * digest_buf = NULL; - size_t digest_len = 0; - rnp_result_t result = RNP_ERROR_GENERIC; - botan_pubkey_t sm2_key = NULL; - int rc; - const pgp_hash_alg_t hash_alg = pgp_hash_alg_type(hash); + rnp_result_t result = RNP_ERROR_GENERIC; + botan_pubkey_t sm2_key = NULL; + int rc; - const char *hash_algo = pgp_hash_name_botan(hash_alg); - digest_len = pgp_digest_length(hash_alg); + const char *hash_algo = rnp::Hash::name_backend(hash.alg()); + size_t digest_len = hash.size(); - digest_buf = (uint8_t *) malloc(digest_len); - - if (digest_buf == NULL) { - result = RNP_ERROR_OUT_OF_MEMORY; - goto done; + uint8_t *digest_buf = (uint8_t *) malloc(digest_len); + if (!digest_buf) { + return RNP_ERROR_OUT_OF_MEMORY; } - if (!sm2_load_public_key(&sm2_key, key)) { + if (!sm2_load_public_key(&sm2_key, &key)) { RNP_LOG("Failed to load SM2 key"); goto done; } @@ -110,30 +106,32 @@ rc = botan_pubkey_sm2_compute_za(digest_buf, &digest_len, ident_field, hash_algo, sm2_key); if (rc != 0) { - printf("compute_za failed %d\n", rc); + RNP_LOG("compute_za failed %d", rc); goto done; } - pgp_hash_add(hash, digest_buf, digest_len); + try { + hash.add(digest_buf, digest_len); + } catch (const std::exception &e) { + RNP_LOG("Failed to update hash: %s", e.what()); + goto done; + } result = RNP_SUCCESS; - done: free(digest_buf); botan_pubkey_destroy(sm2_key); - return result; } rnp_result_t -sm2_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret) +sm2_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) { botan_pubkey_t bpkey = NULL; botan_privkey_t bskey = NULL; rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; - if (!sm2_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng_handle(rng), 0)) { + if (!sm2_load_public_key(&bpkey, key) || botan_pubkey_check_key(bpkey, rng->handle(), 0)) { goto done; } @@ -143,7 +141,7 @@ } if (!sm2_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng_handle(rng), 0)) { + botan_privkey_check_key(bskey, rng->handle(), 0)) { goto done; } ret = RNP_SUCCESS; @@ -154,7 +152,7 @@ } rnp_result_t -sm2_sign(rng_t * rng, +sm2_sign(rnp::RNG * rng, pgp_ec_signature_t *sig, pgp_hash_alg_t hash_alg, const uint8_t * hash, @@ -174,7 +172,7 @@ return RNP_ERROR_NOT_SUPPORTED; } - if (hash_len != pgp_digest_length(hash_alg)) { + if (hash_len != rnp::Hash::size(hash_alg)) { return RNP_ERROR_BAD_PARAMETERS; } @@ -198,7 +196,7 @@ goto end; } - if (botan_pk_op_sign_finish(signer, rng_handle(rng), out_buf, &sig_len)) { + if (botan_pk_op_sign_finish(signer, rng->handle(), out_buf, &sig_len)) { RNP_LOG("Signing failed"); goto end; } @@ -234,7 +232,7 @@ return RNP_ERROR_NOT_SUPPORTED; } - if (hash_len != pgp_digest_length(hash_alg)) { + if (hash_len != rnp::Hash::size(hash_alg)) { return RNP_ERROR_BAD_PARAMETERS; } @@ -277,7 +275,7 @@ } rnp_result_t -sm2_encrypt(rng_t * rng, +sm2_encrypt(rnp::RNG * rng, pgp_sm2_encrypted_t *out, const uint8_t * in, size_t in_len, @@ -297,7 +295,7 @@ return RNP_ERROR_GENERIC; } point_len = BITS_TO_BYTES(curve->bitlen); - hash_alg_len = pgp_digest_length(hash_algo); + hash_alg_len = rnp::Hash::size(hash_algo); if (!hash_alg_len) { RNP_LOG("Unknown hash algorithm for SM2 encryption"); goto done; @@ -323,13 +321,12 @@ it's an all in one scheme, only the hash (used for the integrity check) is specified. */ - if (botan_pk_op_encrypt_create(&enc_op, sm2_key, pgp_hash_name_botan(hash_algo), 0) != 0) { + if (botan_pk_op_encrypt_create(&enc_op, sm2_key, rnp::Hash::name_backend(hash_algo), 0)) { goto done; } out->m.len = sizeof(out->m.mpi); - if (botan_pk_op_encrypt(enc_op, rng_handle(rng), out->m.mpi, &out->m.len, in, in_len) == - 0) { + if (botan_pk_op_encrypt(enc_op, rng->handle(), out->m.mpi, &out->m.len, in, in_len) == 0) { out->m.mpi[out->m.len++] = hash_algo; ret = RNP_SUCCESS; } @@ -365,7 +362,7 @@ } hash_id = in->m.mpi[in_len - 1]; - hash_name = pgp_hash_name_botan((pgp_hash_alg_t) hash_id); + hash_name = rnp::Hash::name_backend((pgp_hash_alg_t) hash_id); if (!hash_name) { RNP_LOG("Unknown hash used in SM2 ciphertext"); goto done; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sm2.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sm2.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sm2.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sm2.h 2022-04-15 07:49:22.000000000 +0000 @@ -27,24 +27,30 @@ #ifndef RNP_SM2_H_ #define RNP_SM2_H_ +#include "config.h" #include "ec.h" typedef struct pgp_sm2_encrypted_t { pgp_mpi_t m; } pgp_sm2_encrypted_t; -rnp_result_t sm2_validate_key(rng_t *rng, const pgp_ec_key_t *key, bool secret); +namespace rnp { +class Hash; +} + +#if defined(ENABLE_SM2) +rnp_result_t sm2_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); /** * Compute the SM2 "ZA" field, and add it to the hash object * * If ident_field is null, uses the default value */ -rnp_result_t sm2_compute_za(const pgp_ec_key_t *key, - pgp_hash_t * hash, +rnp_result_t sm2_compute_za(const pgp_ec_key_t &key, + rnp::Hash & hash, const char * ident_field = NULL); -rnp_result_t sm2_sign(rng_t * rng, +rnp_result_t sm2_sign(rnp::RNG * rng, pgp_ec_signature_t *sig, pgp_hash_alg_t hash_alg, const uint8_t * hash, @@ -57,7 +63,7 @@ size_t hash_len, const pgp_ec_key_t * key); -rnp_result_t sm2_encrypt(rng_t * rng, +rnp_result_t sm2_encrypt(rnp::RNG * rng, pgp_sm2_encrypted_t *out, const uint8_t * in, size_t in_len, @@ -68,5 +74,6 @@ size_t * out_len, const pgp_sm2_encrypted_t *in, const pgp_ec_key_t * key); +#endif // defined(ENABLE_SM2) #endif // SM2_H_ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sm2_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sm2_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/sm2_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/sm2_ossl.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "sm2.h" +#include "hash.h" +#include "utils.h" + +rnp_result_t +sm2_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +{ + return RNP_ERROR_NOT_IMPLEMENTED; +} + +rnp_result_t +sm2_sign(rnp::RNG * rng, + pgp_ec_signature_t *sig, + pgp_hash_alg_t hash_alg, + const uint8_t * hash, + size_t hash_len, + const pgp_ec_key_t *key) +{ + return RNP_ERROR_NOT_IMPLEMENTED; +} + +rnp_result_t +sm2_verify(const pgp_ec_signature_t *sig, + pgp_hash_alg_t hash_alg, + const uint8_t * hash, + size_t hash_len, + const pgp_ec_key_t * key) +{ + return RNP_ERROR_NOT_IMPLEMENTED; +} + +rnp_result_t +sm2_encrypt(rnp::RNG * rng, + pgp_sm2_encrypted_t *out, + const uint8_t * in, + size_t in_len, + pgp_hash_alg_t hash_algo, + const pgp_ec_key_t * key) +{ + return RNP_ERROR_NOT_IMPLEMENTED; +} + +rnp_result_t +sm2_decrypt(uint8_t * out, + size_t * out_len, + const pgp_sm2_encrypted_t *in, + const pgp_ec_key_t * key) +{ + return RNP_ERROR_NOT_IMPLEMENTED; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/symmetric.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/symmetric.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/symmetric.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/symmetric.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -92,12 +92,12 @@ return "AES-256"; #endif -#if defined(BOTAN_HAS_SM4) +#if defined(BOTAN_HAS_SM4) && defined(ENABLE_SM2) case PGP_SA_SM4: return "SM4"; #endif -#if defined(BOTAN_HAS_TWOFISH) +#if defined(BOTAN_HAS_TWOFISH) && defined(ENABLE_TWOFISH) case PGP_SA_TWOFISH: return "Twofish"; #endif @@ -119,6 +119,7 @@ } } +#if defined(ENABLE_AEAD) static bool pgp_aead_to_botan_string(pgp_symm_alg_t ealg, pgp_aead_alg_t aalg, char *buf, size_t len) { @@ -152,6 +153,7 @@ return true; } +#endif bool pgp_cipher_cfb_start(pgp_crypt_t * crypt, @@ -396,7 +398,6 @@ case PGP_SA_CAST5: case PGP_SA_BLOWFISH: return 8; - case PGP_SA_AES_128: case PGP_SA_AES_192: case PGP_SA_AES_256: @@ -406,9 +407,7 @@ case PGP_SA_CAMELLIA_256: case PGP_SA_SM4: return 16; - default: - RNP_DLOG("Unknown PGP symmetric alg %d", (int) alg); return 0; } } @@ -462,6 +461,7 @@ return false; } +#if defined(ENABLE_AEAD) bool pgp_cipher_aead_init(pgp_crypt_t * crypt, pgp_symm_alg_t ealg, @@ -509,6 +509,7 @@ { return crypt->aead.granularity; } +#endif size_t pgp_cipher_aead_nonce_len(pgp_aead_alg_t aalg) @@ -535,6 +536,7 @@ } } +#if defined(ENABLE_AEAD) bool pgp_cipher_aead_set_ad(pgp_crypt_t *crypt, const uint8_t *ad, size_t len) { @@ -655,3 +657,4 @@ return 0; } } +#endif // ENABLE_AEAD diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/symmetric.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/symmetric.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/symmetric.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/symmetric.h 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2017, 2021 [Ribose Inc](https://www.ribose.com). * Copyright (c) 2009 The NetBSD Foundation, Inc. * All rights reserved. * @@ -52,7 +52,12 @@ #ifndef SYMMETRIC_CRYPTO_H_ #define SYMMETRIC_CRYPTO_H_ +#include #include "crypto/rng.h" +#include "config.h" +#ifdef CRYPTO_BACKEND_OPENSSL +#include +#endif /* Nonce len for AEAD/EAX */ #define PGP_AEAD_EAX_NONCE_LEN 16 @@ -76,29 +81,38 @@ #define PGP_AEAD_MAX_AD_LEN 32 struct pgp_crypt_cfb_param_t { +#ifdef CRYPTO_BACKEND_BOTAN struct botan_block_cipher_struct *obj; - size_t remaining; - uint8_t iv[PGP_MAX_BLOCK_SIZE]; +#endif +#ifdef CRYPTO_BACKEND_OPENSSL + EVP_CIPHER_CTX *obj; +#endif + size_t remaining; + uint8_t iv[PGP_MAX_BLOCK_SIZE]; }; struct pgp_crypt_aead_param_t { +#ifdef CRYPTO_BACKEND_BOTAN struct botan_cipher_struct *obj; - pgp_aead_alg_t alg; - bool decrypt; - size_t granularity; - size_t taglen; +#endif + pgp_aead_alg_t alg; + bool decrypt; + size_t granularity; + size_t taglen; }; /** pgp_crypt_t */ typedef struct pgp_crypt_t { union { - struct pgp_crypt_cfb_param_t cfb; + struct pgp_crypt_cfb_param_t cfb; +#if defined(ENABLE_AEAD) struct pgp_crypt_aead_param_t aead; +#endif }; pgp_symm_alg_t alg; size_t blocksize; - rng_t * rng; + rnp::RNG * rng; } pgp_crypt_t; unsigned pgp_block_size(pgp_symm_alg_t); @@ -123,6 +137,7 @@ void pgp_cipher_cfb_resync(pgp_crypt_t *crypt, const uint8_t *buf); +#if defined(ENABLE_AEAD) /** @brief Initialize AEAD cipher instance * @param crypt pgp crypto object * @param ealg symmetric encryption algorithm to use together with AEAD cipher mode @@ -143,6 +158,7 @@ * @return Update granularity value in bytes */ size_t pgp_cipher_aead_granularity(pgp_crypt_t *crypt); +#endif /** @brief Return the AEAD cipher tag length * @param aalg OpenPGP AEAD algorithm @@ -156,6 +172,7 @@ */ size_t pgp_cipher_aead_nonce_len(pgp_aead_alg_t aalg); +#if defined(ENABLE_AEAD) /** @brief Set associated data * @param crypt initialized AEAD crypto * @param ad buffer with data. Cannot be NULL. @@ -221,5 +238,6 @@ const uint8_t *iv, uint8_t * nonce, size_t index); +#endif // ENABLE_AEAD #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/symmetric_ossl.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/symmetric_ossl.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto/symmetric_ossl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto/symmetric_ossl.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,501 @@ +/*- + * Copyright (c) 2021 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "crypto.h" +#include "config.h" +#include "defaults.h" + +#include +#include +#include +#include +#include +#include "utils.h" + +static const char * +pgp_sa_to_openssl_string(pgp_symm_alg_t alg) +{ + switch (alg) { + case PGP_SA_IDEA: + return "idea-ecb"; + case PGP_SA_TRIPLEDES: + return "des-ede3"; + case PGP_SA_CAST5: + return "cast5-ecb"; + case PGP_SA_BLOWFISH: + return "bf-ecb"; + case PGP_SA_AES_128: + return "aes-128-ecb"; + case PGP_SA_AES_192: + return "aes-192-ecb"; + case PGP_SA_AES_256: + return "aes-256-ecb"; + case PGP_SA_SM4: + return "sm4-ecb"; + case PGP_SA_CAMELLIA_128: + return "camellia-128-ecb"; + case PGP_SA_CAMELLIA_192: + return "camellia-192-ecb"; + case PGP_SA_CAMELLIA_256: + return "camellia-256-ecb"; + default: + RNP_LOG("Unsupported PGP symmetric alg %d", (int) alg); + return NULL; + } +} + +bool +pgp_cipher_cfb_start(pgp_crypt_t * crypt, + pgp_symm_alg_t alg, + const uint8_t *key, + const uint8_t *iv) +{ + memset(crypt, 0x0, sizeof(*crypt)); + + const char *cipher_name = pgp_sa_to_openssl_string(alg); + if (!cipher_name) { + RNP_LOG("Unsupported algorithm: %d", alg); + return false; + } + + const EVP_CIPHER *cipher = EVP_get_cipherbyname(cipher_name); + if (!cipher) { + RNP_LOG("Cipher %s is not supported by OpenSSL.", cipher_name); + return false; + } + + crypt->alg = alg; + crypt->blocksize = pgp_block_size(alg); + + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + int res = EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv); + if (res != 1) { + RNP_LOG("Failed to initialize cipher."); + EVP_CIPHER_CTX_free(ctx); + return false; + } + crypt->cfb.obj = ctx; + + if (iv) { + // Otherwise left as all zeros via memset at start of function + memcpy(crypt->cfb.iv, iv, crypt->blocksize); + } + + crypt->cfb.remaining = 0; + return true; +} + +void +pgp_cipher_cfb_resync(pgp_crypt_t *crypt, const uint8_t *buf) +{ + /* iv will be encrypted in the upcoming call to encrypt/decrypt */ + memcpy(crypt->cfb.iv, buf, crypt->blocksize); + crypt->cfb.remaining = 0; +} + +int +pgp_cipher_cfb_finish(pgp_crypt_t *crypt) +{ + if (!crypt) { + return 0; + } + if (crypt->cfb.obj) { + EVP_CIPHER_CTX_free(crypt->cfb.obj); + crypt->cfb.obj = NULL; + } + OPENSSL_cleanse((uint8_t *) crypt, sizeof(*crypt)); + return 0; +} + +/* we rely on fact that in and out could be the same */ +int +pgp_cipher_cfb_encrypt(pgp_crypt_t *crypt, uint8_t *out, const uint8_t *in, size_t bytes) +{ + uint64_t *in64; + uint64_t buf64[512]; // 4KB - page size + uint64_t iv64[2]; + size_t blocks, blockb; + unsigned blsize = crypt->blocksize; + + /* encrypting till the block boundary */ + while (bytes && crypt->cfb.remaining) { + *out = *in++ ^ crypt->cfb.iv[blsize - crypt->cfb.remaining]; + crypt->cfb.iv[blsize - crypt->cfb.remaining] = *out++; + crypt->cfb.remaining--; + bytes--; + } + + if (!bytes) { + return 0; + } + + /* encrypting full blocks */ + if (bytes > blsize) { + memcpy(iv64, crypt->cfb.iv, blsize); + while ((blocks = bytes & ~(blsize - 1)) > 0) { + if (blocks > sizeof(buf64)) { + blocks = sizeof(buf64); + } + bytes -= blocks; + blockb = blocks; + memcpy(buf64, in, blockb); + in64 = buf64; + + if (blsize == 16) { + blocks >>= 4; + while (blocks--) { + int outlen = 16; + EVP_EncryptUpdate( + crypt->cfb.obj, (uint8_t *) iv64, &outlen, (uint8_t *) iv64, 16); + if (outlen != 16) { + RNP_LOG("Bad outlen: must be 16"); + } + *in64 ^= iv64[0]; + iv64[0] = *in64++; + *in64 ^= iv64[1]; + iv64[1] = *in64++; + } + } else { + blocks >>= 3; + while (blocks--) { + int outlen = 8; + EVP_EncryptUpdate( + crypt->cfb.obj, (uint8_t *) iv64, &outlen, (uint8_t *) iv64, 8); + if (outlen != 8) { + RNP_LOG("Bad outlen: must be 8"); + } + *in64 ^= iv64[0]; + iv64[0] = *in64++; + } + } + + memcpy(out, buf64, blockb); + out += blockb; + in += blockb; + } + + memcpy(crypt->cfb.iv, iv64, blsize); + } + + if (!bytes) { + return 0; + } + + int outlen = blsize; + EVP_EncryptUpdate(crypt->cfb.obj, crypt->cfb.iv, &outlen, crypt->cfb.iv, (int) blsize); + if (outlen != (int) blsize) { + RNP_LOG("Bad outlen: must be %u", blsize); + } + crypt->cfb.remaining = blsize; + + /* encrypting tail */ + while (bytes) { + *out = *in++ ^ crypt->cfb.iv[blsize - crypt->cfb.remaining]; + crypt->cfb.iv[blsize - crypt->cfb.remaining] = *out++; + crypt->cfb.remaining--; + bytes--; + } + + return 0; +} + +/* we rely on fact that in and out could be the same */ +int +pgp_cipher_cfb_decrypt(pgp_crypt_t *crypt, uint8_t *out, const uint8_t *in, size_t bytes) +{ + /* for better code readability */ + uint64_t *out64, *in64; + uint64_t inbuf64[512]; // 4KB - page size + uint64_t outbuf64[512]; + uint64_t iv64[2]; + size_t blocks, blockb; + unsigned blsize = crypt->blocksize; + + /* decrypting till the block boundary */ + while (bytes && crypt->cfb.remaining) { + uint8_t c = *in++; + *out++ = c ^ crypt->cfb.iv[blsize - crypt->cfb.remaining]; + crypt->cfb.iv[blsize - crypt->cfb.remaining] = c; + crypt->cfb.remaining--; + bytes--; + } + + if (!bytes) { + return 0; + } + + /* decrypting full blocks */ + if (bytes > blsize) { + memcpy(iv64, crypt->cfb.iv, blsize); + + while ((blocks = bytes & ~(blsize - 1)) > 0) { + if (blocks > sizeof(inbuf64)) { + blocks = sizeof(inbuf64); + } + bytes -= blocks; + blockb = blocks; + memcpy(inbuf64, in, blockb); + out64 = outbuf64; + in64 = inbuf64; + + if (blsize == 16) { + blocks >>= 4; + while (blocks--) { + int outlen = 16; + EVP_EncryptUpdate( + crypt->cfb.obj, (uint8_t *) iv64, &outlen, (uint8_t *) iv64, 16); + if (outlen != 16) { + RNP_LOG("Bad outlen: must be 16"); + } + *out64++ = *in64 ^ iv64[0]; + iv64[0] = *in64++; + *out64++ = *in64 ^ iv64[1]; + iv64[1] = *in64++; + } + } else { + blocks >>= 3; + while (blocks--) { + int outlen = 8; + EVP_EncryptUpdate( + crypt->cfb.obj, (uint8_t *) iv64, &outlen, (uint8_t *) iv64, 8); + if (outlen != 8) { + RNP_LOG("Bad outlen: must be 8"); + } + *out64++ = *in64 ^ iv64[0]; + iv64[0] = *in64++; + } + } + + memcpy(out, outbuf64, blockb); + out += blockb; + in += blockb; + } + + memcpy(crypt->cfb.iv, iv64, blsize); + } + + if (!bytes) { + return 0; + } + + int outlen = blsize; + EVP_EncryptUpdate(crypt->cfb.obj, crypt->cfb.iv, &outlen, crypt->cfb.iv, (int) blsize); + if (outlen != (int) blsize) { + RNP_LOG("Bad outlen: must be %u", blsize); + } + crypt->cfb.remaining = blsize; + + /* decrypting tail */ + while (bytes) { + uint8_t c = *in++; + *out++ = c ^ crypt->cfb.iv[blsize - crypt->cfb.remaining]; + crypt->cfb.iv[blsize - crypt->cfb.remaining] = c; + crypt->cfb.remaining--; + bytes--; + } + + return 0; +} + +size_t +pgp_cipher_block_size(pgp_crypt_t *crypt) +{ + return crypt->blocksize; +} + +unsigned +pgp_block_size(pgp_symm_alg_t alg) +{ + switch (alg) { + case PGP_SA_IDEA: + case PGP_SA_TRIPLEDES: + case PGP_SA_CAST5: + case PGP_SA_BLOWFISH: + return 8; + case PGP_SA_AES_128: + case PGP_SA_AES_192: + case PGP_SA_AES_256: + case PGP_SA_TWOFISH: + case PGP_SA_CAMELLIA_128: + case PGP_SA_CAMELLIA_192: + case PGP_SA_CAMELLIA_256: + case PGP_SA_SM4: + return 16; + default: + return 0; + } +} + +unsigned +pgp_key_size(pgp_symm_alg_t alg) +{ + /* Update MAX_SYMM_KEY_SIZE after adding algorithm + * with bigger key size. + */ + static_assert(32 == MAX_SYMM_KEY_SIZE, "MAX_SYMM_KEY_SIZE must be updated"); + + switch (alg) { + case PGP_SA_IDEA: + case PGP_SA_CAST5: + case PGP_SA_BLOWFISH: + case PGP_SA_AES_128: + case PGP_SA_CAMELLIA_128: + case PGP_SA_SM4: + return 16; + case PGP_SA_TRIPLEDES: + case PGP_SA_AES_192: + case PGP_SA_CAMELLIA_192: + return 24; + case PGP_SA_TWOFISH: + case PGP_SA_AES_256: + case PGP_SA_CAMELLIA_256: + return 32; + default: + return 0; + } +} + +bool +pgp_is_sa_supported(pgp_symm_alg_t alg) +{ + const char *cipher_name = pgp_sa_to_openssl_string(alg); + if (cipher_name) { + return true; + } + RNP_LOG("Warning: cipher %d not supported", (int) alg); + return false; +} + +#if defined(ENABLE_AEAD) +bool +pgp_cipher_aead_init(pgp_crypt_t * crypt, + pgp_symm_alg_t ealg, + pgp_aead_alg_t aalg, + const uint8_t *key, + bool decrypt) +{ + return false; +} + +size_t +pgp_cipher_aead_granularity(pgp_crypt_t *crypt) +{ + return crypt->aead.granularity; +} +#endif + +size_t +pgp_cipher_aead_nonce_len(pgp_aead_alg_t aalg) +{ + switch (aalg) { + case PGP_AEAD_EAX: + return PGP_AEAD_EAX_NONCE_LEN; + case PGP_AEAD_OCB: + return PGP_AEAD_OCB_NONCE_LEN; + default: + return 0; + } +} + +size_t +pgp_cipher_aead_tag_len(pgp_aead_alg_t aalg) +{ + switch (aalg) { + case PGP_AEAD_EAX: + case PGP_AEAD_OCB: + return PGP_AEAD_EAX_OCB_TAG_LEN; + default: + return 0; + } +} + +#if defined(ENABLE_AEAD) +bool +pgp_cipher_aead_set_ad(pgp_crypt_t *crypt, const uint8_t *ad, size_t len) +{ + return false; +} + +bool +pgp_cipher_aead_start(pgp_crypt_t *crypt, const uint8_t *nonce, size_t len) +{ + return false; +} + +bool +pgp_cipher_aead_update(pgp_crypt_t *crypt, uint8_t *out, const uint8_t *in, size_t len) +{ + return false; +} + +void +pgp_cipher_aead_reset(pgp_crypt_t *crypt) +{ + ; +} + +bool +pgp_cipher_aead_finish(pgp_crypt_t *crypt, uint8_t *out, const uint8_t *in, size_t len) +{ + return false; +} + +void +pgp_cipher_aead_destroy(pgp_crypt_t *crypt) +{ + ; +} + +size_t +pgp_cipher_aead_nonce(pgp_aead_alg_t aalg, const uint8_t *iv, uint8_t *nonce, size_t index) +{ + switch (aalg) { + case PGP_AEAD_EAX: + /* The nonce for EAX mode is computed by treating the starting + initialization vector as a 16-octet, big-endian value and + exclusive-oring the low eight octets of it with the chunk index. + */ + memcpy(nonce, iv, PGP_AEAD_EAX_NONCE_LEN); + for (int i = 15; (i > 7) && index; i--) { + nonce[i] ^= index & 0xff; + index = index >> 8; + } + return PGP_AEAD_EAX_NONCE_LEN; + case PGP_AEAD_OCB: + /* The nonce for a chunk of chunk index "i" in OCB processing is defined as: + OCB-Nonce_{i} = IV[1..120] xor i + */ + memcpy(nonce, iv, PGP_AEAD_OCB_NONCE_LEN); + for (int i = 14; (i >= 0) && index; i--) { + nonce[i] ^= index & 0xff; + index = index >> 8; + } + return PGP_AEAD_OCB_NONCE_LEN; + default: + return 0; + } +} +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -81,82 +81,82 @@ #include "utils.h" bool -pgp_generate_seckey(const rnp_keygen_crypto_params_t *crypto, - pgp_key_pkt_t * seckey, +pgp_generate_seckey(const rnp_keygen_crypto_params_t &crypto, + pgp_key_pkt_t & seckey, bool primary) { - if (!crypto || !seckey) { - RNP_LOG("NULL args"); - return false; - } - /* populate pgp key structure */ - *seckey = {}; - seckey->version = PGP_V4; - seckey->creation_time = time(NULL); - seckey->alg = crypto->key_alg; - seckey->material.alg = crypto->key_alg; - seckey->tag = primary ? PGP_PKT_SECRET_KEY : PGP_PKT_SECRET_SUBKEY; + seckey = {}; + seckey.version = PGP_V4; + seckey.creation_time = time(NULL); + seckey.alg = crypto.key_alg; + seckey.material.alg = crypto.key_alg; + seckey.tag = primary ? PGP_PKT_SECRET_KEY : PGP_PKT_SECRET_SUBKEY; - switch (seckey->alg) { + switch (seckey.alg) { case PGP_PKA_RSA: - if (rsa_generate(crypto->rng, &seckey->material.rsa, crypto->rsa.modulus_bit_len)) { + if (rsa_generate(&crypto.ctx->rng, &seckey.material.rsa, crypto.rsa.modulus_bit_len)) { RNP_LOG("failed to generate RSA key"); return false; } break; case PGP_PKA_DSA: - if (dsa_generate(crypto->rng, - &seckey->material.dsa, - crypto->dsa.p_bitlen, - crypto->dsa.q_bitlen)) { + if (dsa_generate(&crypto.ctx->rng, + &seckey.material.dsa, + crypto.dsa.p_bitlen, + crypto.dsa.q_bitlen)) { RNP_LOG("failed to generate DSA key"); return false; } break; case PGP_PKA_EDDSA: - if (eddsa_generate( - crypto->rng, &seckey->material.ec, get_curve_desc(PGP_CURVE_ED25519)->bitlen)) { + if (eddsa_generate(&crypto.ctx->rng, &seckey.material.ec)) { RNP_LOG("failed to generate EDDSA key"); return false; } break; case PGP_PKA_ECDH: - if (!ecdh_set_params(&seckey->material.ec, crypto->ecc.curve)) { - RNP_LOG("Unsupported curve [ID=%d]", crypto->ecc.curve); + if (!ecdh_set_params(&seckey.material.ec, crypto.ecc.curve)) { + RNP_LOG("Unsupported curve [ID=%d]", crypto.ecc.curve); return false; } - if (crypto->ecc.curve == PGP_CURVE_25519) { - if (x25519_generate(crypto->rng, &seckey->material.ec)) { + if (crypto.ecc.curve == PGP_CURVE_25519) { + if (x25519_generate(&crypto.ctx->rng, &seckey.material.ec)) { RNP_LOG("failed to generate x25519 key"); return false; } - seckey->material.ec.curve = crypto->ecc.curve; + seckey.material.ec.curve = crypto.ecc.curve; break; } - /* FALLS THROUGH for non-x25519 curves */ + [[fallthrough]]; case PGP_PKA_ECDSA: case PGP_PKA_SM2: - if (ec_generate(crypto->rng, &seckey->material.ec, seckey->alg, crypto->ecc.curve)) { + if (!curve_supported(crypto.ecc.curve)) { + RNP_LOG("EC generate: curve %d is not supported.", (int) crypto.ecc.curve); + return false; + } + if (ec_generate(&crypto.ctx->rng, &seckey.material.ec, seckey.alg, crypto.ecc.curve)) { RNP_LOG("failed to generate EC key"); return false; } - seckey->material.ec.curve = crypto->ecc.curve; + seckey.material.ec.curve = crypto.ecc.curve; break; case PGP_PKA_ELGAMAL: - if (elgamal_generate(crypto->rng, &seckey->material.eg, crypto->elgamal.key_bitlen)) { + if (elgamal_generate( + &crypto.ctx->rng, &seckey.material.eg, crypto.elgamal.key_bitlen)) { RNP_LOG("failed to generate ElGamal key"); return false; } break; default: - RNP_LOG("key generation not implemented for PK alg: %d", seckey->alg); + RNP_LOG("key generation not implemented for PK alg: %d", seckey.alg); return false; } - seckey->sec_protection.s2k.usage = PGP_S2KU_NONE; - seckey->material.secret = true; + seckey.sec_protection.s2k.usage = PGP_S2KU_NONE; + seckey.material.secret = true; + seckey.material.validity.mark_valid(); /* fill the sec_data/sec_len */ - if (encrypt_secret_key(seckey, NULL, NULL)) { + if (encrypt_secret_key(&seckey, NULL, crypto.ctx->rng)) { RNP_LOG("failed to fill sec_data"); return false; } @@ -195,7 +195,7 @@ } rnp_result_t -validate_pgp_key_material(const pgp_key_material_t *material, rng_t *rng) +validate_pgp_key_material(const pgp_key_material_t *material, rnp::RNG *rng) { #ifdef FUZZERS_ENABLED /* do not timeout on large keys during fuzzing */ @@ -211,14 +211,30 @@ case PGP_PKA_EDDSA: return eddsa_validate_key(rng, &material->ec, material->secret); case PGP_PKA_ECDH: + if (!curve_supported(material->ec.curve)) { + /* allow to import key if curve is not supported */ + RNP_LOG("ECDH validate: curve %d is not supported.", (int) material->ec.curve); + return RNP_SUCCESS; + } return ecdh_validate_key(rng, &material->ec, material->secret); case PGP_PKA_ECDSA: + if (!curve_supported(material->ec.curve)) { + /* allow to import key if curve is not supported */ + RNP_LOG("ECDH validate: curve %d is not supported.", (int) material->ec.curve); + return RNP_SUCCESS; + } return ecdsa_validate_key(rng, &material->ec, material->secret); case PGP_PKA_SM2: +#if defined(ENABLE_SM2) return sm2_validate_key(rng, &material->ec, material->secret); +#else + RNP_LOG("SM2 key validation is not available."); + return RNP_ERROR_NOT_IMPLEMENTED; +#endif case PGP_PKA_ELGAMAL: case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - return elgamal_validate_key(rng, &material->eg, material->secret); + return elgamal_validate_key(&material->eg, material->secret) ? RNP_SUCCESS : + RNP_ERROR_GENERIC; default: RNP_LOG("unknown public key algorithm: %d", (int) material->alg); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/crypto.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/crypto.h 2022-04-15 07:49:22.000000000 +0000 @@ -60,8 +60,8 @@ #include /* raw key generation */ -bool pgp_generate_seckey(const rnp_keygen_crypto_params_t *params, - pgp_key_pkt_t * seckey, +bool pgp_generate_seckey(const rnp_keygen_crypto_params_t ¶ms, + pgp_key_pkt_t & seckey, bool primary); /** generate a new primary key @@ -73,10 +73,10 @@ * @param primary_pub pointer to store the generated public key, must not be NULL * @return true if successful, false otherwise. **/ -bool pgp_generate_primary_key(rnp_keygen_primary_desc_t *desc, +bool pgp_generate_primary_key(rnp_keygen_primary_desc_t &desc, bool merge_defaults, - pgp_key_t * primary_sec, - pgp_key_t * primary_pub, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, pgp_key_store_format_t secformat); /** generate a new subkey @@ -94,18 +94,17 @@ * decrypt the primary key, may be NULL if primary key is unlocked * @return true if successful, false otherwise. **/ -bool pgp_generate_subkey(rnp_keygen_subkey_desc_t * desc, +bool pgp_generate_subkey(rnp_keygen_subkey_desc_t & desc, bool merge_defaults, - pgp_key_t * primary_sec, - pgp_key_t * primary_pub, - pgp_key_t * subkey_sec, - pgp_key_t * subkey_pub, - const pgp_password_provider_t *password_provider, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, + pgp_key_t & subkey_sec, + pgp_key_t & subkey_pub, + const pgp_password_provider_t &password_provider, pgp_key_store_format_t secformat); /** generate a new primary key and subkey * - * @param rng initialized RNG * @param primary_desc primary keygen description * @param subkey_desc subkey keygen description * @param merge_defaults true if you want defaults to be set for unset @@ -116,14 +115,13 @@ * @param subkey_pub pointer to store the generated public key, must not be NULL * @return true if successful, false otherwise. **/ -bool pgp_generate_keypair(rng_t * rng, - rnp_keygen_primary_desc_t *primary_desc, - rnp_keygen_subkey_desc_t * subkey_desc, +bool pgp_generate_keypair(rnp_keygen_primary_desc_t &primary_desc, + rnp_keygen_subkey_desc_t & subkey_desc, bool merge_defaults, - pgp_key_t * primary_sec, - pgp_key_t * primary_pub, - pgp_key_t * subkey_sec, - pgp_key_t * subkey_pub, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, + pgp_key_t & subkey_sec, + pgp_key_t & subkey_pub, pgp_key_store_format_t secformat); /** @@ -136,6 +134,6 @@ */ bool key_material_equal(const pgp_key_material_t *key1, const pgp_key_material_t *key2); -rnp_result_t validate_pgp_key_material(const pgp_key_material_t *material, rng_t *rng); +rnp_result_t validate_pgp_key_material(const pgp_key_material_t *material, rnp::RNG *rng); #endif /* CRYPTO_H_ */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/ffi-priv-types.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/ffi-priv-types.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/ffi-priv-types.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/ffi-priv-types.h 2022-04-15 07:49:22.000000000 +0000 @@ -30,6 +30,7 @@ #include "utils.h" #include #include +#include "sec_profile.hpp" struct rnp_key_handle_st { rnp_ffi_t ffi; @@ -74,9 +75,15 @@ void * getkeycb_ctx; rnp_password_cb getpasscb; void * getpasscb_ctx; - rng_t rng; pgp_key_provider_t key_provider; pgp_password_provider_t pass_provider; + rnp::SecurityContext context; + + rnp_ffi_st(pgp_key_store_format_t pub_fmt, pgp_key_store_format_t sec_fmt); + ~rnp_ffi_st(); + + rnp::RNG & rng() noexcept; + rnp::SecurityProfile &profile() noexcept; }; struct rnp_input_st { @@ -177,6 +184,12 @@ rnp_op_sign_signatures_t signatures{}; }; +#define RNP_LOCATOR_MAX_SIZE (MAX_ID_LENGTH + 1) +static_assert(RNP_LOCATOR_MAX_SIZE > PGP_FINGERPRINT_SIZE * 2, "Locator size mismatch."); +static_assert(RNP_LOCATOR_MAX_SIZE > PGP_KEY_ID_SIZE * 2, "Locator size mismatch."); +static_assert(RNP_LOCATOR_MAX_SIZE > PGP_KEY_GRIP_SIZE * 2, "Locator size mismatch."); +static_assert(RNP_LOCATOR_MAX_SIZE > MAX_ID_LENGTH, "Locator size mismatch."); + struct rnp_identifier_iterator_st { rnp_ffi_t ffi; pgp_key_search_type_t type; @@ -184,9 +197,7 @@ std::list::iterator *keyp; unsigned uididx; json_object * tbl; - char - buf[1 + MAX(MAX(MAX(PGP_KEY_ID_SIZE * 2, PGP_KEY_GRIP_SIZE), PGP_FINGERPRINT_SIZE * 2), - MAX_ID_LENGTH)]; + char buf[RNP_LOCATOR_MAX_SIZE]; }; /* This is just for readability at the call site and will hopefully reduce mistakes. diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/fingerprint.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/fingerprint.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/fingerprint.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/fingerprint.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -40,35 +40,33 @@ rnp_result_t pgp_fingerprint(pgp_fingerprint_t &fp, const pgp_key_pkt_t &key) { - pgp_hash_t hash = {0}; - if ((key.version == PGP_V2) || (key.version == PGP_V3)) { if (!is_rsa_key_alg(key.alg)) { RNP_LOG("bad algorithm"); return RNP_ERROR_NOT_SUPPORTED; } - if (!pgp_hash_create(&hash, PGP_HASH_MD5)) { - RNP_LOG("bad md5 alloc"); - return RNP_ERROR_NOT_SUPPORTED; + try { + rnp::Hash hash(PGP_HASH_MD5); + hash.add(key.material.rsa.n); + hash.add(key.material.rsa.e); + fp.length = hash.finish(fp.fingerprint); + return RNP_SUCCESS; + } catch (const std::exception &e) { + RNP_LOG("Failed to calculate v3 fingerprint: %s", e.what()); + return RNP_ERROR_BAD_STATE; } - (void) mpi_hash(&key.material.rsa.n, &hash); - (void) mpi_hash(&key.material.rsa.e, &hash); - fp.length = pgp_hash_finish(&hash, fp.fingerprint); - RNP_DHEX("v2/v3 fingerprint", fp.fingerprint, fp.length); - return RNP_SUCCESS; } if (key.version == PGP_V4) { - if (!pgp_hash_create(&hash, PGP_HASH_SHA1)) { - RNP_LOG("bad sha1 alloc"); - return RNP_ERROR_NOT_SUPPORTED; - } - if (!signature_hash_key(&key, &hash)) { - return RNP_ERROR_GENERIC; + try { + rnp::Hash hash(PGP_HASH_SHA1); + signature_hash_key(key, hash); + fp.length = hash.finish(fp.fingerprint); + return RNP_SUCCESS; + } catch (const std::exception &e) { + RNP_LOG("Failed to calculate v4 fingerprint: %s", e.what()); + return RNP_ERROR_BAD_STATE; } - fp.length = pgp_hash_finish(&hash, fp.fingerprint); - RNP_DHEX("sha1 fingerprint", fp.fingerprint, fp.length); - return RNP_SUCCESS; } RNP_LOG("unsupported key version"); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/generate-key.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/generate-key.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/generate-key.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/generate-key.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -37,13 +37,13 @@ #include "utils.h" static const uint8_t DEFAULT_SYMMETRIC_ALGS[] = { - PGP_SA_AES_256, PGP_SA_AES_192, PGP_SA_AES_128, PGP_SA_TRIPLEDES}; + PGP_SA_AES_256, PGP_SA_AES_192, PGP_SA_AES_128}; static const uint8_t DEFAULT_HASH_ALGS[] = { - PGP_HASH_SHA256, PGP_HASH_SHA384, PGP_HASH_SHA512, PGP_HASH_SHA224, PGP_HASH_SHA1}; + PGP_HASH_SHA256, PGP_HASH_SHA384, PGP_HASH_SHA512, PGP_HASH_SHA224}; static const uint8_t DEFAULT_COMPRESS_ALGS[] = { PGP_C_ZLIB, PGP_C_BZIP2, PGP_C_ZIP, PGP_C_NONE}; -static pgp_map_t pubkey_alg_map[] = { +static const id_str_pair pubkey_alg_map[] = { {PGP_PKA_RSA, "RSA (Encrypt or Sign)"}, {PGP_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only"}, {PGP_PKA_RSA_SIGN_ONLY, "RSA Sign-Only"}, @@ -66,21 +66,21 @@ {PGP_PKA_PRIVATE08, "Private/Experimental"}, {PGP_PKA_PRIVATE09, "Private/Experimental"}, {PGP_PKA_PRIVATE10, "Private/Experimental"}, - {0x00, NULL}, /* this is the end-of-array marker */ -}; + {0, NULL}}; static bool -load_generated_g10_key(pgp_key_t * dst, - pgp_key_pkt_t *newkey, - pgp_key_t * primary_key, - pgp_key_t * pubkey) -{ - bool ok = false; - pgp_dest_t memdst = {}; - pgp_source_t memsrc = {}; - rnp_key_store_t * key_store = NULL; - list key_ptrs = NULL; /* holds primary and pubkey, when used */ - pgp_key_provider_t prov = {}; +load_generated_g10_key(pgp_key_t * dst, + pgp_key_pkt_t * newkey, + pgp_key_t * primary_key, + pgp_key_t * pubkey, + rnp::SecurityContext &ctx) +{ + bool ok = false; + pgp_dest_t memdst = {}; + pgp_source_t memsrc = {}; + rnp_key_store_t * key_store = NULL; + std::vector key_ptrs; /* holds primary and pubkey, when used */ + pgp_key_provider_t prov = {}; // this should generally be zeroed assert(dst->type() == 0); @@ -95,30 +95,33 @@ goto end; } - if (!g10_write_seckey(&memdst, newkey, NULL)) { + if (!g10_write_seckey(&memdst, newkey, NULL, ctx.rng)) { RNP_LOG("failed to write generated seckey"); goto end; } // this would be better on the stack but the key store does not allow it try { - key_store = new rnp_key_store_t(); + key_store = new rnp_key_store_t(ctx); } catch (const std::exception &e) { RNP_LOG("%s", e.what()); goto end; } // if this is a subkey, add the primary in first - if (primary_key && !list_append(&key_ptrs, &primary_key, sizeof(primary_key))) { - goto end; - } - // G10 needs the pubkey for copying some attributes (key version, creation time, etc) - if (!list_append(&key_ptrs, &pubkey, sizeof(pubkey))) { + try { + if (primary_key) { + key_ptrs.push_back(primary_key); + } + // G10 needs the pubkey for copying some attributes (key version, creation time, etc) + key_ptrs.push_back(pubkey); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); goto end; } prov.callback = rnp_key_provider_key_ptr_list; - prov.userdata = key_ptrs; + prov.userdata = &key_ptrs; if (init_mem_src(&memsrc, mem_dest_get_memory(&memdst), memdst.writeb, false)) { goto end; @@ -143,7 +146,6 @@ delete key_store; src_close(&memsrc); dst_close(&memdst, true); - list_destroy(&key_ptrs); return ok; } @@ -171,7 +173,7 @@ ecdsa_get_min_hash(crypto.ecc.curve) : dsa_get_min_hash(crypto.dsa.q_bitlen); - if (pgp_digest_length(crypto.hash_alg) < pgp_digest_length(min_hash)) { + if (rnp::Hash::size(crypto.hash_alg) < rnp::Hash::size(min_hash)) { crypto.hash_alg = min_hash; } } @@ -231,30 +233,29 @@ } static bool -validate_keygen_primary(const rnp_keygen_primary_desc_t *desc) +validate_keygen_primary(const rnp_keygen_primary_desc_t &desc) { /* Confirm that the specified pk alg can certify. * gpg requires this, though the RFC only says that a V4 primary * key SHOULD be a key capable of certification. */ - if (!(pgp_pk_alg_capabilities(desc->crypto.key_alg) & PGP_KF_CERTIFY)) { - RNP_LOG("primary key alg (%d) must be able to sign", desc->crypto.key_alg); + if (!(pgp_pk_alg_capabilities(desc.crypto.key_alg) & PGP_KF_CERTIFY)) { + RNP_LOG("primary key alg (%d) must be able to sign", desc.crypto.key_alg); return false; } // check key flags - if (!desc->cert.key_flags) { + if (!desc.cert.key_flags) { // these are probably not *technically* required RNP_LOG("key flags are required"); return false; - } else if (desc->cert.key_flags & ~pgp_pk_alg_capabilities(desc->crypto.key_alg)) { + } else if (desc.cert.key_flags & ~pgp_pk_alg_capabilities(desc.crypto.key_alg)) { // check the flags against the alg capabilities RNP_LOG("usage not permitted for pk algorithm"); return false; } - // require a userid - if (!desc->cert.userid[0]) { + if (!desc.cert.userid[0]) { RNP_LOG("userid is required for primary key"); return false; } @@ -307,12 +308,6 @@ } } -static const char * -pgp_show_pka(pgp_pubkey_alg_t pka) -{ - return pgp_str_from_map(pka, pubkey_alg_map); -} - static void keygen_primary_merge_defaults(rnp_keygen_primary_desc_t &desc) { @@ -327,106 +322,83 @@ snprintf((char *) desc.cert.userid, sizeof(desc.cert.userid), "%s %d-bit key <%s@localhost>", - pgp_show_pka(desc.crypto.key_alg), + id_str_pair::lookup(pubkey_alg_map, desc.crypto.key_alg), get_numbits(&desc.crypto), getenv_logname()); } } bool -pgp_generate_primary_key(rnp_keygen_primary_desc_t *desc, +pgp_generate_primary_key(rnp_keygen_primary_desc_t &desc, bool merge_defaults, - pgp_key_t * primary_sec, - pgp_key_t * primary_pub, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, pgp_key_store_format_t secformat) { // validate args - if (!desc || !primary_pub || !primary_sec) { - return false; - } - if (primary_sec->type() || primary_pub->type()) { + if (primary_sec.type() || primary_pub.type()) { RNP_LOG("invalid parameters (should be zeroed)"); return false; } - // merge some defaults in, if requested - if (merge_defaults) { - try { - keygen_primary_merge_defaults(*desc); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); + try { + // merge some defaults in, if requested + if (merge_defaults) { + keygen_primary_merge_defaults(desc); + } + // now validate the keygen fields + if (!validate_keygen_primary(desc)) { return false; } - } - // now validate the keygen fields - if (!validate_keygen_primary(desc)) { - return false; - } - - // generate the raw key and fill tag/secret fields - pgp_transferable_key_t tkeysec; - if (!pgp_generate_seckey(&desc->crypto, &tkeysec.key, true)) { - return false; - } - - pgp_transferable_userid_t *uid = - transferable_key_add_userid(tkeysec, (char *) desc->cert.userid); - if (!uid) { - RNP_LOG("failed to add userid"); - return false; - } - - if (!transferable_userid_certify( - tkeysec.key, *uid, tkeysec.key, desc->crypto.hash_alg, desc->cert)) { - RNP_LOG("failed to certify key"); - return false; - } - - pgp_transferable_key_t tkeypub; - try { - tkeypub = pgp_transferable_key_t(tkeysec, true); - *primary_pub = tkeypub; - } catch (const std::exception &e) { - RNP_LOG("failed to copy public key part: %s", e.what()); - return false; - } - - switch (secformat) { - case PGP_KEY_STORE_GPG: - case PGP_KEY_STORE_KBX: - try { - *primary_sec = tkeysec; - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); + // generate the raw key and fill tag/secret fields + pgp_key_pkt_t secpkt; + if (!pgp_generate_seckey(desc.crypto, secpkt, true)) { return false; } - break; - case PGP_KEY_STORE_G10: - if (!load_generated_g10_key(primary_sec, &tkeysec.key, NULL, primary_pub)) { - RNP_LOG("failed to load generated key"); + + pgp_key_t sec(secpkt); + pgp_key_t pub(secpkt, true); + sec.add_uid_cert(desc.cert, desc.crypto.hash_alg, *desc.crypto.ctx, &pub); + + switch (secformat) { + case PGP_KEY_STORE_GPG: + case PGP_KEY_STORE_KBX: + primary_sec = std::move(sec); + primary_pub = std::move(pub); + break; + case PGP_KEY_STORE_G10: + primary_pub = std::move(pub); + if (!load_generated_g10_key( + &primary_sec, &secpkt, NULL, &primary_pub, *desc.crypto.ctx)) { + RNP_LOG("failed to load generated key"); + return false; + } + break; + default: + RNP_LOG("invalid format"); return false; } - break; - default: - RNP_LOG("invalid format"); + } catch (const std::exception &e) { + RNP_LOG("Failure: %s", e.what()); return false; } /* mark it as valid */ - primary_pub->mark_valid(); - primary_sec->mark_valid(); + primary_pub.mark_valid(); + primary_sec.mark_valid(); /* refresh key's data */ - return primary_pub->refresh_data() && primary_sec->refresh_data(); + return primary_pub.refresh_data(*desc.crypto.ctx) && + primary_sec.refresh_data(*desc.crypto.ctx); } static bool -validate_keygen_subkey(rnp_keygen_subkey_desc_t *desc) +validate_keygen_subkey(rnp_keygen_subkey_desc_t &desc) { - if (!desc->binding.key_flags) { + if (!desc.binding.key_flags) { RNP_LOG("key flags are required"); return false; - } else if (desc->binding.key_flags & ~pgp_pk_alg_capabilities(desc->crypto.key_alg)) { + } else if (desc.binding.key_flags & ~pgp_pk_alg_capabilities(desc.crypto.key_alg)) { // check the flags against the alg capabilities RNP_LOG("usage not permitted for pk algorithm"); return false; @@ -445,201 +417,131 @@ } bool -pgp_generate_subkey(rnp_keygen_subkey_desc_t * desc, +pgp_generate_subkey(rnp_keygen_subkey_desc_t & desc, bool merge_defaults, - pgp_key_t * primary_sec, - pgp_key_t * primary_pub, - pgp_key_t * subkey_sec, - pgp_key_t * subkey_pub, - const pgp_password_provider_t *password_provider, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, + pgp_key_t & subkey_sec, + pgp_key_t & subkey_pub, + const pgp_password_provider_t &password_provider, pgp_key_store_format_t secformat) { - pgp_transferable_subkey_t tskeysec; - pgp_transferable_subkey_t tskeypub; - const pgp_key_pkt_t * primary_seckey = NULL; - pgp_key_pkt_t * decrypted_primary_seckey = NULL; - pgp_password_ctx_t ctx = {}; - bool ok = false; - // validate args - if (!desc || !primary_sec || !primary_pub || !subkey_sec || !subkey_pub) { - RNP_LOG("NULL args"); - goto end; - } - if (!primary_sec->is_primary() || !primary_pub->is_primary() || - !primary_sec->is_secret() || !primary_pub->is_public()) { + if (!primary_sec.is_primary() || !primary_pub.is_primary() || !primary_sec.is_secret() || + !primary_pub.is_public()) { RNP_LOG("invalid parameters"); - goto end; + return false; } - if (subkey_sec->type() || subkey_pub->type()) { + if (subkey_sec.type() || subkey_pub.type()) { RNP_LOG("invalid parameters (should be zeroed)"); - goto end; + return false; } // merge some defaults in, if requested if (merge_defaults) { - keygen_subkey_merge_defaults(*desc); + keygen_subkey_merge_defaults(desc); } // now validate the keygen fields if (!validate_keygen_subkey(desc)) { - goto end; - } - - ctx = {.op = PGP_OP_ADD_SUBKEY, .key = primary_sec}; - - // decrypt the primary seckey if needed (for signatures) - if (primary_sec->encrypted()) { - decrypted_primary_seckey = pgp_decrypt_seckey(primary_sec, password_provider, &ctx); - if (!decrypted_primary_seckey) { - goto end; - } - primary_seckey = decrypted_primary_seckey; - } else { - primary_seckey = &primary_sec->pkt(); - } - - // generate the raw key pair - if (!pgp_generate_seckey(&desc->crypto, &tskeysec.subkey, false)) { - goto end; - } - - if (!transferable_subkey_bind( - *primary_seckey, tskeysec, desc->crypto.hash_alg, desc->binding)) { - RNP_LOG("failed to add subkey binding signature"); - goto end; + return false; } try { - *subkey_pub = pgp_key_t(pgp_transferable_subkey_t(tskeysec, true), primary_pub); - } catch (const std::exception &e) { - RNP_LOG("failed to copy public subkey part: %s", e.what()); - goto end; - } - - switch (secformat) { - case PGP_KEY_STORE_GPG: - case PGP_KEY_STORE_KBX: - try { - *subkey_sec = pgp_key_t(tskeysec, primary_sec); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - goto end; + /* decrypt the primary seckey if needed (for signatures) */ + rnp::KeyLocker primlock(primary_sec); + if (primary_sec.encrypted() && + !primary_sec.unlock(password_provider, PGP_OP_ADD_SUBKEY)) { + RNP_LOG("Failed to unlock primary key."); + return false; } - break; - case PGP_KEY_STORE_G10: - if (!load_generated_g10_key(subkey_sec, &tskeysec.subkey, primary_sec, subkey_pub)) { - RNP_LOG("failed to load generated key"); - goto end; + /* generate the raw subkey */ + pgp_key_pkt_t secpkt; + if (!pgp_generate_seckey(desc.crypto, secpkt, false)) { + return false; + } + pgp_key_pkt_t pubpkt = pgp_key_pkt_t(secpkt, true); + pgp_key_t sec(secpkt, primary_sec); + pgp_key_t pub(pubpkt, primary_pub); + /* add binding */ + primary_sec.add_sub_binding( + sec, pub, desc.binding, desc.crypto.hash_alg, *desc.crypto.ctx); + /* copy to the result */ + subkey_pub = std::move(pub); + switch (secformat) { + case PGP_KEY_STORE_GPG: + case PGP_KEY_STORE_KBX: + subkey_sec = std::move(sec); + break; + case PGP_KEY_STORE_G10: + if (!load_generated_g10_key( + &subkey_sec, &secpkt, &primary_sec, &subkey_pub, *desc.crypto.ctx)) { + RNP_LOG("failed to load generated key"); + return false; + } + break; + default: + RNP_LOG("invalid format"); + return false; } - break; - default: - RNP_LOG("invalid format"); - goto end; - break; - } - subkey_pub->mark_valid(); - subkey_sec->mark_valid(); - ok = subkey_pub->refresh_data(primary_pub) && subkey_sec->refresh_data(primary_sec); -end: - if (decrypted_primary_seckey) { - delete decrypted_primary_seckey; + subkey_pub.mark_valid(); + subkey_sec.mark_valid(); + return subkey_pub.refresh_data(&primary_pub, *desc.crypto.ctx) && + subkey_sec.refresh_data(&primary_sec, *desc.crypto.ctx); + } catch (const std::exception &e) { + RNP_LOG("Subkey generation failed: %s", e.what()); + return false; } - return ok; } static void -keygen_merge_defaults(rnp_keygen_primary_desc_t *primary_desc, - rnp_keygen_subkey_desc_t * subkey_desc) +keygen_merge_defaults(rnp_keygen_primary_desc_t &primary_desc, + rnp_keygen_subkey_desc_t & subkey_desc) { - if (!primary_desc->cert.key_flags && !subkey_desc->binding.key_flags) { + if (!primary_desc.cert.key_flags && !subkey_desc.binding.key_flags) { // if no flags are set for either the primary key nor subkey, // we can set up some typical defaults here (these are validated // later against the alg capabilities) - primary_desc->cert.key_flags = PGP_KF_SIGN | PGP_KF_CERTIFY; - subkey_desc->binding.key_flags = PGP_KF_ENCRYPT; + primary_desc.cert.key_flags = PGP_KF_SIGN | PGP_KF_CERTIFY; + subkey_desc.binding.key_flags = PGP_KF_ENCRYPT; } } -static void -print_keygen_crypto(const rnp_keygen_crypto_params_t *crypto) -{ - printf("key_alg: %s (%d)\n", pgp_show_pka(crypto->key_alg), crypto->key_alg); - if (crypto->key_alg == PGP_PKA_RSA) { - printf("bits: %u\n", crypto->rsa.modulus_bit_len); - } else { - printf("curve: %d\n", crypto->ecc.curve); - } - printf("hash_alg: %s (%d)\n", pgp_show_hash_alg(crypto->hash_alg), crypto->hash_alg); -} - -static void -print_keygen_primary(const rnp_keygen_primary_desc_t *desc) -{ - printf("Keygen (primary)\n"); - print_keygen_crypto(&desc->crypto); -} - -static void -print_keygen_subkey(const rnp_keygen_subkey_desc_t *desc) -{ - printf("Keygen (subkey)\n"); - print_keygen_crypto(&desc->crypto); -} - bool -pgp_generate_keypair(rng_t * rng, - rnp_keygen_primary_desc_t *primary_desc, - rnp_keygen_subkey_desc_t * subkey_desc, +pgp_generate_keypair(rnp_keygen_primary_desc_t &primary_desc, + rnp_keygen_subkey_desc_t & subkey_desc, bool merge_defaults, - pgp_key_t * primary_sec, - pgp_key_t * primary_pub, - pgp_key_t * subkey_sec, - pgp_key_t * subkey_pub, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, + pgp_key_t & subkey_sec, + pgp_key_t & subkey_pub, pgp_key_store_format_t secformat) { - bool ok = false; - - if (rnp_get_debug(__FILE__)) { - print_keygen_primary(primary_desc); - print_keygen_subkey(subkey_desc); - } - - // validate args - if (!primary_desc || !subkey_desc || !primary_sec || !primary_pub || !subkey_sec || - !subkey_pub) { - RNP_LOG("NULL args"); - goto end; - } - // merge some defaults in, if requested if (merge_defaults) { keygen_merge_defaults(primary_desc, subkey_desc); } // generate the primary key - primary_desc->crypto.rng = rng; if (!pgp_generate_primary_key( primary_desc, merge_defaults, primary_sec, primary_pub, secformat)) { RNP_LOG("failed to generate primary key"); - goto end; + return false; } // generate the subkey - subkey_desc->crypto.rng = rng; + pgp_password_provider_t prov = {}; if (!pgp_generate_subkey(subkey_desc, merge_defaults, primary_sec, primary_pub, subkey_sec, subkey_pub, - NULL, + prov, secformat)) { RNP_LOG("failed to generate subkey"); - goto end; + return false; } - ok = true; -end: - return ok; + return true; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/json-utils.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/json-utils.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/json-utils.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/json-utils.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "json-utils.h" +#include "logging.h" +#include "crypto/mem.h" + +/* Shortcut function to add field checking it for null to avoid allocation failure. + Please note that it deallocates val on failure. */ +bool +obj_add_field_json(json_object *obj, const char *name, json_object *val) +{ + if (!val) { + return false; + } + // TODO: in JSON-C 0.13 json_object_object_add returns bool instead of void + json_object_object_add(obj, name, val); + if (!json_object_object_get_ex(obj, name, NULL)) { + json_object_put(val); + return false; + } + + return true; +} + +bool +json_add(json_object *obj, const char *name, const char *value) +{ + return obj_add_field_json(obj, name, json_object_new_string(value)); +} + +bool +json_add(json_object *obj, const char *name, bool value) +{ + return obj_add_field_json(obj, name, json_object_new_boolean(value)); +} + +bool +json_add(json_object *obj, const char *name, const char *value, size_t len) +{ + return obj_add_field_json(obj, name, json_object_new_string_len(value, len)); +} + +bool +obj_add_hex_json(json_object *obj, const char *name, const uint8_t *val, size_t val_len) +{ + if (val_len > 1024 * 1024) { + RNP_LOG("too large json hex field: %zu", val_len); + val_len = 1024 * 1024; + } + + char smallbuf[64] = {0}; + size_t hexlen = val_len * 2 + 1; + + char *hexbuf = hexlen < sizeof(smallbuf) ? smallbuf : (char *) malloc(hexlen); + if (!hexbuf) { + return false; + } + + bool res = rnp::hex_encode(val, val_len, hexbuf, hexlen, rnp::HEX_LOWERCASE) && + obj_add_field_json(obj, name, json_object_new_string(hexbuf)); + + if (hexbuf != smallbuf) { + free(hexbuf); + } + return res; +} + +bool +array_add_element_json(json_object *obj, json_object *val) +{ + if (!val) { + return false; + } + if (json_object_array_add(obj, val)) { + json_object_put(val); + return false; + } + return true; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/json_utils.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/json_utils.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/json_utils.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/json_utils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019, [Ribose Inc](https://www.ribose.com). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef RNP_JSON_UTILS_H_ -#define RNP_JSON_UTILS_H_ - -#include -#include "types.h" -#include -#include "json_object.h" -#include "json.h" - -/** - * @brief Add field to the json object. - * Note: this function is for convenience, it will check val for NULL and destroy val - * on failure. - * @param obj allocated json_object of object type. - * @param name name of the field - * @param val json object of any type. Will be checked for NULL. - * @return true if val is not NULL and field was added successfully, false otherwise. - */ -bool obj_add_field_json(json_object *obj, const char *name, json_object *val); - -/** - * @brief Add hex representation of binary data as string field to JSON object. - * Note: this function follows conventions of obj_add_field_json(). - */ -bool obj_add_hex_json(json_object *obj, const char *name, const uint8_t *val, size_t val_len); - -/** - * @brief Add element to JSON array. - * Note: this function follows convention of the obj_add_field_json. - */ -bool array_add_element_json(json_object *obj, json_object *val); - -#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/json-utils.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/json-utils.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/json-utils.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/json-utils.h 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef RNP_JSON_UTILS_H_ +#define RNP_JSON_UTILS_H_ + +#include +#include "types.h" +#include +#include "json_object.h" +#include "json.h" + +/** + * @brief Add field to the json object. + * Note: this function is for convenience, it will check val for NULL and destroy val + * on failure. + * @param obj allocated json_object of object type. + * @param name name of the field + * @param val json object of any type. Will be checked for NULL. + * @return true if val is not NULL and field was added successfully, false otherwise. + */ +bool obj_add_field_json(json_object *obj, const char *name, json_object *val); + +/** + * @brief Shortcut to add string via obj_add_field_json(). + */ +bool json_add(json_object *obj, const char *name, const char *value); + +/** + * @brief Shortcut to add string with length via obj_add_field_json(). + */ +bool json_add(json_object *obj, const char *name, const char *value, size_t len); + +/** + * @brief Shortcut to add bool via obj_add_field_json(). + */ +bool json_add(json_object *obj, const char *name, bool value); + +/** + * @brief Add hex representation of binary data as string field to JSON object. + * Note: this function follows conventions of obj_add_field_json(). + */ +bool obj_add_hex_json(json_object *obj, const char *name, const uint8_t *val, size_t val_len); + +/** + * @brief Add element to JSON array. + * Note: this function follows convention of the obj_add_field_json. + */ +bool array_add_element_json(json_object *obj, json_object *val); + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/key-provider.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/key-provider.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/key-provider.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/key-provider.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -78,9 +78,8 @@ pgp_key_t * rnp_key_provider_key_ptr_list(const pgp_key_request_ctx_t *ctx, void *userdata) { - list key_list = (list) userdata; - for (list_item *item = list_front(key_list); item; item = list_next(item)) { - pgp_key_t *key = *(pgp_key_t **) item; + std::vector *key_list = (std::vector *) userdata; + for (auto key : *key_list) { if (rnp_key_matches_search(key, &ctx->search) && (key->is_secret() == ctx->secret)) { return key; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/librnp.symbols thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/librnp.symbols --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/librnp.symbols 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/librnp.symbols 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1 @@ +_rnp_* diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/librnp.vsc thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/librnp.vsc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/librnp.vsc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/librnp.vsc 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,4 @@ +{ + global: rnp_*; + local: *; +}; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/misc.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/misc.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/misc.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/misc.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,324 +0,0 @@ -/* - * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com). - * Copyright (c) 2009-2010 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and - * carried further by Ribose Inc (https://www.ribose.com). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ -#include "config.h" - -#ifdef HAVE_SYS_CDEFS_H -#include -#endif - -#if defined(__NetBSD__) -__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: misc.c,v 1.41 2012/03/05 02:20:18 christos Exp $"); -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#include -#else -#include "uniwin.h" -#endif - -#include "crypto.h" -#include "crypto/mem.h" -#include "utils.h" -#include "json_utils.h" - -#ifdef _WIN32 -#include -#include -#include -#define vsnprintf _vsnprintf -#endif - -/** - * Searches the given map for the given type. - * Returns a human-readable descriptive string if found, - * returns NULL if not found - * - * It is the responsibility of the calling function to handle the - * error case sensibly (i.e. don't just print out the return string. - * - */ -static const char * -str_from_map_or_null(int type, pgp_map_t *map) -{ - pgp_map_t *row; - - for (row = map; row->string != NULL; row++) { - if (row->type == type) { - return row->string; - } - } - return NULL; -} - -/** - * \ingroup Core_Print - * - * Searches the given map for the given type. - * Returns a readable string if found, "Unknown" if not. - */ - -const char * -pgp_str_from_map(int type, pgp_map_t *map) -{ - const char *str; - - str = str_from_map_or_null(type, map); - return (str) ? str : "Unknown"; -} - -#define LINELEN 16 - -/* show hexadecimal/ascii dump */ -void -hexdump(FILE *fp, const char *header, const uint8_t *src, size_t length) -{ - size_t i; - char line[LINELEN + 1]; - - (void) fprintf(fp, "%s%s", (header) ? header : "", (header) ? "" : ""); - (void) fprintf(fp, " (%zu byte%s):\n", length, (length == 1) ? "" : "s"); - for (i = 0; i < length; i++) { - if (i % LINELEN == 0) { - (void) fprintf(fp, "%.5zu | ", i); - } - (void) fprintf(fp, "%.02x ", (uint8_t) src[i]); - line[i % LINELEN] = (isprint(src[i])) ? src[i] : '.'; - if (i % LINELEN == LINELEN - 1) { - line[LINELEN] = 0x0; - (void) fprintf(fp, " | %s\n", line); - } - } - if (i % LINELEN != 0) { - for (; i % LINELEN != 0; i++) { - (void) fprintf(fp, " "); - line[i % LINELEN] = ' '; - } - line[LINELEN] = 0x0; - (void) fprintf(fp, " | %s\n", line); - } -} - -/* small useful functions for setting the file-level debugging levels */ -/* if the debugv list contains the filename in question, we're debugging it */ - -enum { MAX_DEBUG_NAMES = 32 }; - -static int debugc; -static char *debugv[MAX_DEBUG_NAMES]; - -/* set the debugging level per filename */ -bool -rnp_set_debug(const char *f) -{ - const char *name; - int i; - - if (f == NULL) { - f = "all"; - } - if ((name = strrchr(f, '/')) == NULL) { - name = f; - } else { - name += 1; - } - for (i = 0; ((i < MAX_DEBUG_NAMES) && (i < debugc)); i++) { - if (strcmp(debugv[i], name) == 0) { - return true; - } - } - if (i == MAX_DEBUG_NAMES) { - return false; - } - debugv[debugc++] = strdup(name); - return debugv[debugc - 1] != NULL; -} - -/* get the debugging level per filename */ -bool -rnp_get_debug(const char *f) -{ - const char *name; - int i; - - if (!debugc) { - return false; - } - - if ((name = strrchr(f, '/')) == NULL) { - name = f; - } else { - name += 1; - } - for (i = 0; i < debugc; i++) { - if (strcmp(debugv[i], "all") == 0 || strcmp(debugv[i], name) == 0) { - return true; - } - } - return false; -} - -void -rnp_clear_debug() -{ - for (int i = 0; i < debugc; i++) { - free(debugv[i]); - debugv[i] = NULL; - } - debugc = 0; -} - -/* portable replacement for strcasecmp(3) */ -int -rnp_strcasecmp(const char *s1, const char *s2) -{ - int n; - - for (; (n = tolower((uint8_t) *s1) - tolower((uint8_t) *s2)) == 0 && *s1; s1++, s2++) { - } - return n; -} - -/* return the hexdump as a string */ -char * -rnp_strhexdump_upper(char *dest, const uint8_t *src, size_t length, const char *sep) -{ - unsigned i; - int n; - - for (n = 0, i = 0; i < length; i += 2) { - n += snprintf(&dest[n], 3, "%02X", *src++); - n += snprintf(&dest[n], 10, "%02X%s", *src++, sep); - } - return dest; -} - -char * -rnp_strlwr(char *s) -{ - char *p = s; - while (*p) { - *p = tolower((unsigned char) *p); - p++; - } - return s; -} - -/* Shortcut function to add field checking it for null to avoid allocation failure. - Please note that it deallocates val on failure. */ -bool -obj_add_field_json(json_object *obj, const char *name, json_object *val) -{ - if (!val) { - return false; - } - // TODO: in JSON-C 0.13 json_object_object_add returns bool instead of void - json_object_object_add(obj, name, val); - if (!json_object_object_get_ex(obj, name, NULL)) { - json_object_put(val); - return false; - } - - return true; -} - -bool -obj_add_hex_json(json_object *obj, const char *name, const uint8_t *val, size_t val_len) -{ - if (val_len > 1024 * 1024) { - RNP_LOG("too large json hex field: %zu", val_len); - val_len = 1024 * 1024; - } - - char smallbuf[64] = {0}; - size_t hexlen = val_len * 2 + 1; - - char *hexbuf = hexlen < sizeof(smallbuf) ? smallbuf : (char *) malloc(hexlen); - if (!hexbuf) { - return false; - } - - bool res = rnp::hex_encode(val, val_len, hexbuf, hexlen, rnp::HEX_LOWERCASE) && - obj_add_field_json(obj, name, json_object_new_string(hexbuf)); - - if (hexbuf != smallbuf) { - free(hexbuf); - } - return res; -} - -bool -array_add_element_json(json_object *obj, json_object *val) -{ - if (!val) { - return false; - } - if (json_object_array_add(obj, val)) { - json_object_put(val); - return false; - } - return true; -} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/pgp-key.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/pgp-key.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/pgp-key.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/pgp-key.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -56,6 +56,7 @@ #include "crypto.h" #include "crypto/s2k.h" #include "crypto/mem.h" +#include "crypto/signatures.h" #include "fingerprint.h" #include @@ -73,15 +74,14 @@ #include "defaults.h" pgp_key_pkt_t * -pgp_decrypt_seckey_pgp(const uint8_t * data, - size_t data_len, - const pgp_key_pkt_t *pubkey, - const char * password) +pgp_decrypt_seckey_pgp(const pgp_rawpacket_t &raw, + const pgp_key_pkt_t & pubkey, + const char * password) { pgp_source_t src = {0}; pgp_key_pkt_t *res = NULL; - if (init_mem_src(&src, data, data_len, false)) { + if (init_mem_src(&src, raw.raw.data(), raw.raw.size(), false)) { return NULL; } try { @@ -112,41 +112,32 @@ * key->key.seckey by parsing the key data in packets[0]. */ pgp_key_pkt_t * -pgp_decrypt_seckey(const pgp_key_t * key, - const pgp_password_provider_t *provider, - const pgp_password_ctx_t * ctx) -{ - typedef struct pgp_key_pkt_t *pgp_seckey_decrypt_t( - const uint8_t *data, size_t data_len, const pgp_key_pkt_t *pubkey, const char *password); - pgp_seckey_decrypt_t *decryptor = NULL; - +pgp_decrypt_seckey(const pgp_key_t & key, + const pgp_password_provider_t &provider, + const pgp_password_ctx_t & ctx) +{ // sanity checks - if (!key || !key->is_secret() || !provider) { + if (!key.is_secret()) { RNP_LOG("invalid args"); return NULL; } - switch (key->format) { + // ask the provider for a password + rnp::secure_array password; + if (key.is_protected() && + !pgp_request_password(&provider, &ctx, password.data(), password.size())) { + return NULL; + } + // attempt to decrypt with the provided password + switch (key.format) { case PGP_KEY_STORE_GPG: case PGP_KEY_STORE_KBX: - decryptor = pgp_decrypt_seckey_pgp; - break; + return pgp_decrypt_seckey_pgp(key.rawpkt(), key.pkt(), password.data()); case PGP_KEY_STORE_G10: - decryptor = g10_decrypt_seckey; - break; + return g10_decrypt_seckey(key.rawpkt(), key.pkt(), password.data()); default: - RNP_LOG("unexpected format: %d", key->format); + RNP_LOG("unexpected format: %d", key.format); return NULL; } - - // ask the provider for a password - rnp::secure_array password; - if (key->is_protected() && - !pgp_request_password(provider, ctx, password.data(), password.size())) { - return NULL; - } - // attempt to decrypt with the provided password - const pgp_rawpacket_t &pkt = key->rawpkt(); - return decryptor(pkt.raw.data(), pkt.raw.size(), &key->pkt(), password.data()); } pgp_key_t * @@ -177,13 +168,13 @@ return pgp_request_key(prov, &ctx); } -static pgp_map_t ss_rr_code_map[] = { +static const id_str_pair ss_rr_code_map[] = { {PGP_REVOCATION_NO_REASON, "No reason specified"}, {PGP_REVOCATION_SUPERSEDED, "Key is superseded"}, {PGP_REVOCATION_COMPROMISED, "Key material has been compromised"}, {PGP_REVOCATION_RETIRED, "Key is retired and no longer used"}, {PGP_REVOCATION_NO_LONGER_VALID, "User ID information is no longer valid"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; pgp_key_t * @@ -235,13 +226,16 @@ } bool -pgp_key_t::write_sec_pgp(pgp_dest_t &dst, pgp_key_pkt_t &seckey, const std::string &password) +pgp_key_t::write_sec_pgp(pgp_dest_t & dst, + pgp_key_pkt_t & seckey, + const std::string &password, + rnp::RNG & rng) { bool res = false; pgp_pkt_type_t oldtag = seckey.tag; seckey.tag = type(); - if (encrypt_secret_key(&seckey, password.c_str(), NULL)) { + if (encrypt_secret_key(&seckey, password.c_str(), rng)) { goto done; } try { @@ -256,7 +250,7 @@ } bool -pgp_key_t::write_sec_rawpkt(pgp_key_pkt_t &seckey, const std::string &password) +pgp_key_t::write_sec_rawpkt(pgp_key_pkt_t &seckey, const std::string &password, rnp::RNG &rng) { pgp_dest_t memdst = {}; if (init_mem_dest(&memdst, NULL, 0)) { @@ -269,13 +263,13 @@ switch (format) { case PGP_KEY_STORE_GPG: case PGP_KEY_STORE_KBX: - if (!write_sec_pgp(memdst, seckey, password)) { + if (!write_sec_pgp(memdst, seckey, password, rng)) { RNP_LOG("failed to write secret key"); goto done; } break; case PGP_KEY_STORE_G10: - if (!g10_write_seckey(&memdst, &seckey, password.c_str())) { + if (!g10_write_seckey(&memdst, &seckey, password.c_str(), rng)) { RNP_LOG("failed to write g10 secret key"); goto done; } @@ -297,67 +291,6 @@ return ret; } -bool -pgp_key_add_userid_certified(pgp_key_t * key, - const pgp_key_pkt_t * seckey, - pgp_hash_alg_t hash_alg, - rnp_selfsig_cert_info_t *cert) -{ - // sanity checks - if (!key || !seckey || !cert || !cert->userid[0]) { - RNP_LOG("wrong parameters"); - return false; - } - // userids are only valid for primary keys, not subkeys - if (!key->is_primary()) { - RNP_LOG("cannot add a userid to a subkey"); - return false; - } - // see if the key already has this userid - if (key->has_uid((const char *) cert->userid)) { - RNP_LOG("key already has this userid"); - return false; - } - // this isn't really valid for this format - if (key->format == PGP_KEY_STORE_G10) { - RNP_LOG("Unsupported key store type"); - return false; - } - // We only support modifying v4 and newer keys - if (key->pkt().version < PGP_V4) { - RNP_LOG("adding a userid to V2/V3 key is not supported"); - return false; - } - // TODO: changing the primary userid is not currently supported - if (key->has_primary_uid() && cert->primary) { - RNP_LOG("changing the primary userid is not supported"); - return false; - } - - /* Fill the transferable userid */ - pgp_transferable_userid_t uid; - uid.uid.tag = PGP_PKT_USER_ID; - uid.uid.uid_len = strlen((char *) cert->userid); - if (!(uid.uid.uid = (uint8_t *) malloc(uid.uid.uid_len))) { - RNP_LOG("allocation failed"); - return false; - } - /* uid.uid.uid looks really weird */ - memcpy(uid.uid.uid, (char *) cert->userid, uid.uid.uid_len); - if (!transferable_userid_certify(*seckey, uid, *seckey, hash_alg, *cert)) { - RNP_LOG("failed to add userid certification"); - return false; - } - try { - key->add_uid(uid); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return false; - } - - return key->refresh_data(); -} - static bool update_sig_expiration(pgp_signature_t *dst, const pgp_signature_t *src, uint32_t expiry) { @@ -380,7 +313,8 @@ pgp_key_set_expiration(pgp_key_t * key, pgp_key_t * seckey, uint32_t expiry, - const pgp_password_provider_t &prov) + const pgp_password_provider_t &prov, + rnp::SecurityContext & ctx) { if (!key->is_primary()) { RNP_LOG("Not a primary key"); @@ -405,8 +339,7 @@ return false; } - bool locked = false; - bool res = false; + rnp::KeyLocker seclock(*seckey); for (const auto &sigid : sigs) { pgp_subsig_t &sig = key->get_sig(sigid); /* update signature and re-sign it */ @@ -415,8 +348,7 @@ } /* unlock secret key if needed */ - locked = seckey->is_locked(); - if (locked && !seckey->unlock(prov)) { + if (seckey->is_locked() && !seckey->unlock(prov)) { RNP_LOG("Failed to unlock secret key"); return false; } @@ -424,28 +356,20 @@ pgp_signature_t newsig; pgp_sig_id_t oldsigid = sigid; if (!update_sig_expiration(&newsig, &sig.sig, expiry)) { - goto done; - } - if (sig.is_cert()) { - if (sig.uid >= key->uid_count()) { - RNP_LOG("uid not found"); - goto done; - } - if (!signature_calculate_certification( - &key->pkt(), &key->get_uid(sig.uid).pkt, &newsig, &seckey->pkt())) { - RNP_LOG("failed to calculate signature"); - goto done; - } - } else { - /* direct-key signature case */ - if (!signature_calculate_direct(&key->pkt(), &newsig, &seckey->pkt())) { - RNP_LOG("failed to calculate signature"); - goto done; - } + return false; } - - /* replace signature, first for secret key since it may be replaced in public */ try { + if (sig.is_cert()) { + if (sig.uid >= key->uid_count()) { + RNP_LOG("uid not found"); + return false; + } + seckey->sign_cert(key->pkt(), key->get_uid(sig.uid).pkt, newsig, ctx); + } else { + /* direct-key signature case */ + seckey->sign_direct(key->pkt(), newsig, ctx); + } + /* replace signature, first for secret key since it may be replaced in public */ if (seckey->has_sig(oldsigid)) { seckey->replace_sig(oldsigid, newsig); } @@ -453,25 +377,20 @@ key->replace_sig(oldsigid, newsig); } } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - goto done; + RNP_LOG("failed to calculate or add signature: %s", e.what()); + return false; } } - if (!seckey->refresh_data()) { + if (!seckey->refresh_data(ctx)) { RNP_LOG("Failed to refresh seckey data."); - goto done; + return false; } - if ((key != seckey) && !key->refresh_data()) { + if ((key != seckey) && !key->refresh_data(ctx)) { RNP_LOG("Failed to refresh key data."); - goto done; - } - res = true; -done: - if (locked) { - seckey->lock(); + return false; } - return res; + return true; } bool @@ -479,7 +398,8 @@ pgp_key_t * primsec, pgp_key_t * secsub, uint32_t expiry, - const pgp_password_provider_t &prov) + const pgp_password_provider_t &prov, + rnp::SecurityContext & ctx) { if (!sub->is_subkey()) { RNP_LOG("Not a subkey"); @@ -496,64 +416,42 @@ return true; } - bool res = false; - bool subsign = secsub->can_sign(); - bool locked = primsec->is_locked(); - if (locked && !primsec->unlock(prov)) { + rnp::KeyLocker primlock(*primsec); + if (primsec->is_locked() && !primsec->unlock(prov)) { RNP_LOG("Failed to unlock primary key"); return false; } - pgp_signature_t newsig; - pgp_sig_id_t oldsigid = subsig->sigid; - bool sublocked = false; - if (subsign && secsub->is_locked()) { - if (!secsub->unlock(prov)) { - RNP_LOG("Failed to unlock subkey"); - goto done; - } - sublocked = true; - } - - /* update signature and re-sign */ - if (!update_sig_expiration(&newsig, &subsig->sig, expiry)) { - goto done; - } - if (!signature_calculate_binding(&primsec->pkt(), &secsub->pkt(), &newsig, subsign)) { - RNP_LOG("failed to calculate signature"); - goto done; + bool subsign = secsub->can_sign(); + rnp::KeyLocker sublock(*secsub); + if (subsign && secsub->is_locked() && !secsub->unlock(prov)) { + RNP_LOG("Failed to unlock subkey"); + return false; } - /* replace signature, first for the secret key since it may be replaced in public */ - if (secsub->has_sig(oldsigid)) { - try { + try { + /* update signature and re-sign */ + pgp_signature_t newsig; + pgp_sig_id_t oldsigid = subsig->sigid; + if (!update_sig_expiration(&newsig, &subsig->sig, expiry)) { + return false; + } + primsec->sign_subkey_binding(*secsub, newsig, ctx); + /* replace signature, first for the secret key since it may be replaced in public */ + if (secsub->has_sig(oldsigid)) { secsub->replace_sig(oldsigid, newsig); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - goto done; + if (!secsub->refresh_data(primsec, ctx)) { + return false; + } } - if (!secsub->refresh_data(primsec)) { - goto done; + if (sub == secsub) { + return true; } - } - if (sub == secsub) { - res = true; - goto done; - } - try { sub->replace_sig(oldsigid, newsig); + return sub->refresh_data(primsec, ctx); } catch (const std::exception &e) { RNP_LOG("%s", e.what()); - goto done; - } - res = sub->refresh_data(primsec); -done: - if (locked) { - primsec->lock(); - } - if (sublocked) { - secsub->lock(); + return false; } - return res; } pgp_key_t * @@ -601,7 +499,7 @@ hash_min = dsa_get_min_hash(mpi_bits(&pubkey->material.dsa.q)); } - if (pgp_digest_length(hash) < pgp_digest_length(hash_min)) { + if (rnp::Hash::size(hash) < rnp::Hash::size(hash_min)) { return hash_min; } return hash; @@ -887,7 +785,7 @@ reason = sig.sig.revocation_reason(); } if (reason.empty()) { - reason = pgp_str_from_map(code, ss_rr_code_map); + reason = id_str_pair::lookup(ss_rr_code_map, code); } } @@ -908,12 +806,19 @@ RNP_LOG("failed to setup key fields"); throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } + /* decryption resets validity */ + pkt_.material.validity = keypkt.material.validity; } /* add rawpacket */ rawpkt_ = pgp_rawpacket_t(pkt_); format = PGP_KEY_STORE_GPG; } +pgp_key_t::pgp_key_t(const pgp_key_pkt_t &pkt, pgp_key_t &primary) : pgp_key_t(pkt) +{ + primary.link_subkey_fp(*this); +} + pgp_key_t::pgp_key_t(const pgp_key_t &src, bool pubonly) { /* Do some checks for g10 keys */ @@ -1039,9 +944,15 @@ auto &res = sigs_map_.emplace(std::make_pair(newsig.get_id(), newsig)).first->second; res.uid = uid; auto it = std::find(sigs_.begin(), sigs_.end(), oldid); + if (it == sigs_.end()) { + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } *it = res.sigid; if (uid == PGP_UID_NONE) { auto it = std::find(keysigs_.begin(), keysigs_.end(), oldid); + if (it == keysigs_.end()) { + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } *it = res.sigid; } else { uids_[uid].replace_sig(oldid, res.sigid); @@ -1275,8 +1186,8 @@ pkt_ = pkt; } -const pgp_key_material_t & -pgp_key_t::material() const +pgp_key_material_t & +pgp_key_t::material() { return pkt_.material; } @@ -1295,7 +1206,7 @@ case PGP_PKA_ECDSA: case PGP_PKA_EDDSA: case PGP_PKA_SM2: - return material().ec.curve; + return pkt_.material.ec.curve; default: return PGP_CURVE_UNKNOWN; } @@ -1578,7 +1489,7 @@ } bool -pgp_key_t::unlock(const pgp_password_provider_t &provider) +pgp_key_t::unlock(const pgp_password_provider_t &provider, pgp_op_t op) { // sanity checks if (!is_secret()) { @@ -1590,8 +1501,8 @@ return true; } - pgp_password_ctx_t ctx = {.op = PGP_OP_UNLOCK, .key = this}; - pgp_key_pkt_t * decrypted_seckey = pgp_decrypt_seckey(this, &provider, &ctx); + pgp_password_ctx_t ctx = {.op = (uint8_t) op, .key = this}; + pgp_key_pkt_t * decrypted_seckey = pgp_decrypt_seckey(*this, provider, ctx); if (!decrypted_seckey) { return false; } @@ -1625,7 +1536,8 @@ bool pgp_key_t::protect(const rnp_key_protection_params_t &protection, - const pgp_password_provider_t & password_provider) + const pgp_password_provider_t & password_provider, + rnp::RNG & rng) { pgp_password_ctx_t ctx; memset(&ctx, 0, sizeof(ctx)); @@ -1637,13 +1549,14 @@ if (!pgp_request_password(&password_provider, &ctx, password.data(), password.size())) { return false; } - return protect(pkt_, protection, password.data()); + return protect(pkt_, protection, password.data(), rng); } bool pgp_key_t::protect(pgp_key_pkt_t & decrypted, const rnp_key_protection_params_t &protection, - const std::string & new_password) + const std::string & new_password, + rnp::RNG & rng) { if (!is_secret()) { RNP_LOG("Warning: this is not a secret key"); @@ -1677,11 +1590,11 @@ } /* write the protected key to raw packet */ - return write_sec_rawpkt(decrypted, new_password); + return write_sec_rawpkt(decrypted, new_password, rng); } bool -pgp_key_t::unprotect(const pgp_password_provider_t &password_provider) +pgp_key_t::unprotect(const pgp_password_provider_t &password_provider, rnp::RNG &rng) { /* sanity check */ if (!is_secret()) { @@ -1695,7 +1608,7 @@ /* simple case */ if (!encrypted()) { pkt_.sec_protection.s2k.usage = PGP_S2KU_NONE; - return write_sec_rawpkt(pkt_, ""); + return write_sec_rawpkt(pkt_, "", rng); } pgp_password_ctx_t ctx; @@ -1703,12 +1616,12 @@ ctx.op = PGP_OP_UNPROTECT; ctx.key = this; - pgp_key_pkt_t *decrypted_seckey = pgp_decrypt_seckey(this, &password_provider, &ctx); + pgp_key_pkt_t *decrypted_seckey = pgp_decrypt_seckey(*this, password_provider, ctx); if (!decrypted_seckey) { return false; } decrypted_seckey->sec_protection.s2k.usage = PGP_S2KU_NONE; - if (!write_sec_rawpkt(*decrypted_seckey, "")) { + if (!write_sec_rawpkt(*decrypted_seckey, "", rng)) { delete decrypted_seckey; return false; } @@ -1829,7 +1742,7 @@ pgp_key_t::latest_selfsig(uint32_t uid) { uint32_t latest = 0; - pgp_subsig_t *res = NULL; + pgp_subsig_t *res = nullptr; for (auto &sigid : sigs_) { auto &sig = get_sig(sigid); @@ -1843,7 +1756,8 @@ break; case PGP_UID_PRIMARY: { pgp_sig_subpkt_t *subpkt = sig.sig.get_subpkt(PGP_SIG_SUBPKT_PRIMARY_USER_ID); - skip = !is_self_cert(sig) || !subpkt || !subpkt->fields.primary_uid; + skip = !is_self_cert(sig) || !subpkt || !subpkt->fields.primary_uid || + (sig.uid == PGP_UID_NONE); break; } case PGP_UID_ANY: @@ -1863,6 +1777,14 @@ res = &sig; } } + + /* if there is later self-sig for the same uid without primary flag, then drop res */ + if ((uid == PGP_UID_PRIMARY) && res) { + pgp_subsig_t *overres = latest_selfsig(res->uid); + if (overres && (overres->sig.creation() > res->sig.creation())) { + res = nullptr; + } + } return res; } @@ -1975,59 +1897,64 @@ } void -pgp_key_t::validate_sig(const pgp_key_t &key, pgp_subsig_t &sig) const +pgp_key_t::validate_sig(const pgp_key_t & key, + pgp_subsig_t & sig, + const rnp::SecurityContext &ctx) const noexcept { sig.validity.reset(); pgp_signature_info_t sinfo = {}; sinfo.sig = &sig.sig; - sinfo.signer = this; sinfo.signer_valid = true; if (key.is_self_cert(sig) || key.is_binding(sig)) { sinfo.ignore_expiry = true; } pgp_sig_type_t stype = sig.sig.type(); - switch (stype) { - case PGP_SIG_BINARY: - case PGP_SIG_TEXT: - case PGP_SIG_STANDALONE: - case PGP_SIG_PRIMARY: - RNP_LOG("Invalid key signature type: %d", (int) stype); - return; - case PGP_CERT_GENERIC: - case PGP_CERT_PERSONA: - case PGP_CERT_CASUAL: - case PGP_CERT_POSITIVE: - case PGP_SIG_REV_CERT: { - if (sig.uid >= key.uid_count()) { - RNP_LOG("Userid not found"); - return; - } - signature_check_certification(&sinfo, &key.pkt(), &key.get_uid(sig.uid).pkt); - break; - } - case PGP_SIG_SUBKEY: - if (!is_signer(sig)) { - RNP_LOG("Invalid subkey binding's signer."); + try { + switch (stype) { + case PGP_SIG_BINARY: + case PGP_SIG_TEXT: + case PGP_SIG_STANDALONE: + case PGP_SIG_PRIMARY: + RNP_LOG("Invalid key signature type: %d", (int) stype); return; + case PGP_CERT_GENERIC: + case PGP_CERT_PERSONA: + case PGP_CERT_CASUAL: + case PGP_CERT_POSITIVE: + case PGP_SIG_REV_CERT: { + if (sig.uid >= key.uid_count()) { + RNP_LOG("Userid not found"); + return; + } + validate_cert(sinfo, key.pkt(), key.get_uid(sig.uid).pkt, ctx); + break; } - signature_check_binding(&sinfo, &this->pkt(), &key); - break; - case PGP_SIG_DIRECT: - case PGP_SIG_REV_KEY: - signature_check_direct(&sinfo, &key.pkt()); - break; - case PGP_SIG_REV_SUBKEY: - if (!is_signer(sig)) { - RNP_LOG("Invalid subkey revocation's signer."); + case PGP_SIG_SUBKEY: + if (!is_signer(sig)) { + RNP_LOG("Invalid subkey binding's signer."); + return; + } + validate_binding(sinfo, key, ctx); + break; + case PGP_SIG_DIRECT: + case PGP_SIG_REV_KEY: + validate_direct(sinfo, ctx); + break; + case PGP_SIG_REV_SUBKEY: + if (!is_signer(sig)) { + RNP_LOG("Invalid subkey revocation's signer."); + return; + } + validate_sub_rev(sinfo, key.pkt(), ctx); + break; + default: + RNP_LOG("Unsupported key signature type: %d", (int) stype); return; } - signature_check_subkey_revocation(&sinfo, &this->pkt(), &key.pkt()); - break; - default: - RNP_LOG("Unsupported key signature type: %d", (int) stype); - return; + } catch (const std::exception &e) { + RNP_LOG("Key signature validation failed: %s", e.what()); } sig.validity.validated = true; @@ -2040,7 +1967,139 @@ } void -pgp_key_t::validate_self_signatures() +pgp_key_t::validate_sig(pgp_signature_info_t & sinfo, + rnp::Hash & hash, + const rnp::SecurityContext &ctx) const noexcept +{ + sinfo.no_signer = false; + sinfo.valid = false; + sinfo.expired = false; + + /* Validate signature itself */ + if (sinfo.signer_valid || valid_at(sinfo.sig->creation())) { + sinfo.valid = !signature_validate(*sinfo.sig, pkt_.material, hash, ctx); + } else { + sinfo.valid = false; + RNP_LOG("invalid or untrusted key"); + } + + /* Check signature's expiration time */ + uint32_t now = time(NULL); + uint32_t create = sinfo.sig->creation(); + uint32_t expiry = sinfo.sig->expiration(); + if (create > now) { + /* signature created later then now */ + RNP_LOG("signature created %d seconds in future", (int) (create - now)); + sinfo.expired = true; + } + if (create && expiry && (create + expiry < now)) { + /* signature expired */ + RNP_LOG("signature expired"); + sinfo.expired = true; + } + + /* check key creation time vs signature creation */ + if (creation() > create) { + RNP_LOG("key is newer than signature"); + sinfo.valid = false; + } + + /* check whether key was not expired when sig created */ + if (!sinfo.ignore_expiry && expiration() && (creation() + expiration() < create)) { + RNP_LOG("signature made after key expiration"); + sinfo.valid = false; + } + + /* Check signer's fingerprint */ + if (sinfo.sig->has_keyfp() && (sinfo.sig->keyfp() != fp())) { + RNP_LOG("issuer fingerprint doesn't match signer's one"); + sinfo.valid = false; + } + + /* Check for unknown critical notations */ + for (auto &subpkt : sinfo.sig->subpkts) { + if (!subpkt.critical || (subpkt.type != PGP_SIG_SUBPKT_NOTATION_DATA)) { + continue; + } + std::string name(subpkt.fields.notation.name, + subpkt.fields.notation.name + subpkt.fields.notation.nlen); + RNP_LOG("unknown critical notation: %s", name.c_str()); + sinfo.valid = false; + } +} + +void +pgp_key_t::validate_cert(pgp_signature_info_t & sinfo, + const pgp_key_pkt_t & key, + const pgp_userid_pkt_t & uid, + const rnp::SecurityContext &ctx) const +{ + rnp::Hash hash; + signature_hash_certification(*sinfo.sig, key, uid, hash); + validate_sig(sinfo, hash, ctx); +} + +void +pgp_key_t::validate_binding(pgp_signature_info_t & sinfo, + const pgp_key_t & subkey, + const rnp::SecurityContext &ctx) const +{ + rnp::Hash hash; + signature_hash_binding(*sinfo.sig, pkt(), subkey.pkt(), hash); + validate_sig(sinfo, hash, ctx); + if (!sinfo.valid || !(sinfo.sig->key_flags() & PGP_KF_SIGN)) { + return; + } + + /* check primary key binding signature if any */ + sinfo.valid = false; + pgp_sig_subpkt_t *subpkt = sinfo.sig->get_subpkt(PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE, false); + if (!subpkt) { + RNP_LOG("error! no primary key binding signature"); + return; + } + if (!subpkt->parsed) { + RNP_LOG("invalid embedded signature subpacket"); + return; + } + if (subpkt->fields.sig->type() != PGP_SIG_PRIMARY) { + RNP_LOG("invalid primary key binding signature"); + return; + } + if (subpkt->fields.sig->version < PGP_V4) { + RNP_LOG("invalid primary key binding signature version"); + return; + } + + signature_hash_binding(*subpkt->fields.sig, pkt(), subkey.pkt(), hash); + pgp_signature_info_t bindinfo = {}; + bindinfo.sig = subpkt->fields.sig; + bindinfo.signer_valid = true; + bindinfo.ignore_expiry = true; + subkey.validate_sig(bindinfo, hash, ctx); + sinfo.valid = bindinfo.valid && !bindinfo.expired; +} + +void +pgp_key_t::validate_sub_rev(pgp_signature_info_t & sinfo, + const pgp_key_pkt_t & subkey, + const rnp::SecurityContext &ctx) const +{ + rnp::Hash hash; + signature_hash_binding(*sinfo.sig, pkt(), subkey, hash); + validate_sig(sinfo, hash, ctx); +} + +void +pgp_key_t::validate_direct(pgp_signature_info_t &sinfo, const rnp::SecurityContext &ctx) const +{ + rnp::Hash hash; + signature_hash_direct(*sinfo.sig, pkt(), hash); + validate_sig(sinfo, hash, ctx); +} + +void +pgp_key_t::validate_self_signatures(const rnp::SecurityContext &ctx) { for (auto &sigid : sigs_) { pgp_subsig_t &sig = get_sig(sigid); @@ -2050,13 +2109,13 @@ if (is_direct_self(sig) || is_self_cert(sig) || is_uid_revocation(sig) || is_revocation(sig)) { - validate_sig(*this, sig); + validate_sig(*this, sig, ctx); } } } void -pgp_key_t::validate_self_signatures(pgp_key_t &primary) +pgp_key_t::validate_self_signatures(pgp_key_t &primary, const rnp::SecurityContext &ctx) { for (auto &sigid : sigs_) { pgp_subsig_t &sig = get_sig(sigid); @@ -2065,7 +2124,7 @@ } if (is_binding(sig) || is_revocation(sig)) { - primary.validate_sig(*this, sig); + primary.validate_sig(*this, sig, ctx); } } } @@ -2074,10 +2133,10 @@ pgp_key_t::validate_primary(rnp_key_store_t &keyring) { /* validate signatures if needed */ - validate_self_signatures(); + validate_self_signatures(keyring.secctx); /* consider public key as valid on this level if it is not expired and has at least one - * valid self-signature (or it is secret), and is not revoked */ + * valid self-signature, and is not revoked */ validity_.reset(); validity_.validated = true; bool has_cert = false; @@ -2111,8 +2170,8 @@ has_cert = !has_expired; } - /* we have at least one non-expiring key self-signature or secret key */ - if (has_cert || is_secret()) { + /* we have at least one non-expiring key self-signature */ + if (has_cert) { validity_.valid = true; return; } @@ -2128,7 +2187,7 @@ if (!sub) { continue; } - sub->validate_self_signatures(*this); + sub->validate_self_signatures(*this, keyring.secctx); pgp_subsig_t *sig = sub->latest_binding(); if (!sig) { continue; @@ -2143,17 +2202,17 @@ } void -pgp_key_t::validate_subkey(pgp_key_t *primary) +pgp_key_t::validate_subkey(pgp_key_t *primary, const rnp::SecurityContext &ctx) { /* consider subkey as valid on this level if it has valid primary key, has at least one - * non-expired binding signature (or is secret), and is not revoked. */ + * non-expired binding signature, and is not revoked. */ validity_.reset(); validity_.validated = true; if (!primary || !primary->valid()) { return; } /* validate signatures if needed */ - validate_self_signatures(*primary); + validate_self_signatures(*primary, ctx); bool has_binding = false; bool has_expired = false; @@ -2174,7 +2233,7 @@ return; } } - validity_.valid = has_binding || (is_secret() && primary->is_secret()); + validity_.valid = has_binding; if (!validity_.valid) { validity_.expired = has_expired; } @@ -2191,7 +2250,7 @@ if (has_primary_fp()) { primary = rnp_key_store_get_key_by_fpr(&keyring, primary_fp()); } - validate_subkey(primary); + validate_subkey(primary, keyring.secctx); } } @@ -2203,21 +2262,21 @@ if (primary) { primary->revalidate(keyring); } else { - validate_subkey(NULL); + validate_subkey(NULL, keyring.secctx); } return; } validate(keyring); - if (!refresh_data()) { + if (!refresh_data(keyring.secctx)) { RNP_LOG("Failed to refresh key data"); } /* validate/re-validate all subkeys as well */ for (auto &fp : subkey_fps_) { pgp_key_t *subkey = rnp_key_store_get_key_by_fpr(&keyring, fp); if (subkey) { - subkey->validate_subkey(this); - if (!subkey->refresh_data(this)) { + subkey->validate_subkey(this, keyring.secctx); + if (!subkey->refresh_data(this, keyring.secctx)) { RNP_LOG("Failed to refresh subkey data"); } } @@ -2233,15 +2292,195 @@ } } +void +pgp_key_t::sign_init(pgp_signature_t &sig, pgp_hash_alg_t hash) const +{ + sig.version = PGP_V4; + sig.halg = pgp_hash_adjust_alg_to_key(hash, &pkt_); + sig.palg = alg(); + sig.set_keyfp(fp()); + sig.set_creation(time(NULL)); + sig.set_keyid(keyid()); +} + +void +pgp_key_t::sign_cert(const pgp_key_pkt_t & key, + const pgp_userid_pkt_t &uid, + pgp_signature_t & sig, + rnp::SecurityContext & ctx) +{ + rnp::Hash hash; + sig.fill_hashed_data(); + signature_hash_certification(sig, key, uid, hash); + signature_calculate(sig, pkt_.material, hash, ctx); +} + +void +pgp_key_t::sign_direct(const pgp_key_pkt_t & key, + pgp_signature_t & sig, + rnp::SecurityContext &ctx) +{ + rnp::Hash hash; + sig.fill_hashed_data(); + signature_hash_direct(sig, key, hash); + signature_calculate(sig, pkt_.material, hash, ctx); +} + +void +pgp_key_t::sign_binding(const pgp_key_pkt_t & key, + pgp_signature_t & sig, + rnp::SecurityContext &ctx) +{ + rnp::Hash hash; + sig.fill_hashed_data(); + if (is_primary()) { + signature_hash_binding(sig, pkt(), key, hash); + } else { + signature_hash_binding(sig, key, pkt(), hash); + } + signature_calculate(sig, pkt_.material, hash, ctx); +} + +void +pgp_key_t::gen_revocation(const pgp_revoke_t & revoke, + pgp_hash_alg_t hash, + const pgp_key_pkt_t & key, + pgp_signature_t & sig, + rnp::SecurityContext &ctx) +{ + sign_init(sig, hash); + sig.set_type(is_primary_key_pkt(key.tag) ? PGP_SIG_REV_KEY : PGP_SIG_REV_SUBKEY); + sig.set_revocation_reason(revoke.code, revoke.reason); + + if (is_primary_key_pkt(key.tag)) { + sign_direct(key, sig, ctx); + } else { + sign_binding(key, sig, ctx); + } +} + +void +pgp_key_t::sign_subkey_binding(pgp_key_t & sub, + pgp_signature_t & sig, + rnp::SecurityContext &ctx, + bool subsign) +{ + if (!is_primary()) { + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + sign_binding(sub.pkt(), sig, ctx); + /* add primary key binding subpacket if requested */ + if (subsign) { + pgp_signature_t embsig; + sub.sign_init(embsig, sig.halg); + embsig.set_type(PGP_SIG_PRIMARY); + sub.sign_binding(pkt(), embsig, ctx); + sig.set_embedded_sig(embsig); + } +} + +void +pgp_key_t::add_uid_cert(rnp_selfsig_cert_info_t &cert, + pgp_hash_alg_t hash, + rnp::SecurityContext & ctx, + pgp_key_t * pubkey) +{ + if (!cert.userid[0]) { + /* todo: why not to allow empty uid? */ + RNP_LOG("wrong parameters"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + // userids are only valid for primary keys, not subkeys + if (!is_primary()) { + RNP_LOG("cannot add a userid to a subkey"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + // see if the key already has this userid + if (has_uid((const char *) cert.userid)) { + RNP_LOG("key already has this userid"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + // this isn't really valid for this format + if (format == PGP_KEY_STORE_G10) { + RNP_LOG("Unsupported key store type"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + // We only support modifying v4 and newer keys + if (pkt().version < PGP_V4) { + RNP_LOG("adding a userid to V2/V3 key is not supported"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + /* TODO: if key has at least one uid then has_primary_uid() will be always true! */ + if (has_primary_uid() && cert.primary) { + RNP_LOG("changing the primary userid is not supported"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + + /* Fill the transferable userid */ + pgp_userid_pkt_t uid; + pgp_signature_t sig; + sign_init(sig, hash); + cert.populate(uid, sig); + try { + sign_cert(pkt_, uid, sig, ctx); + } catch (const std::exception &e) { + RNP_LOG("Failed to certify: %s", e.what()); + throw; + } + /* add uid and signature to the key and pubkey, if non-NULL */ + uids_.emplace_back(uid); + add_sig(sig, uid_count() - 1); + refresh_data(ctx); + if (!pubkey) { + return; + } + pubkey->uids_.emplace_back(uid); + pubkey->add_sig(sig, pubkey->uid_count() - 1); + pubkey->refresh_data(ctx); +} + +void +pgp_key_t::add_sub_binding(pgp_key_t & subsec, + pgp_key_t & subpub, + const rnp_selfsig_binding_info_t &binding, + pgp_hash_alg_t hash, + rnp::SecurityContext & ctx) +{ + if (!is_primary()) { + RNP_LOG("must be called on primary key"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + + /* populate signature */ + pgp_signature_t sig; + sign_init(sig, hash); + sig.set_type(PGP_SIG_SUBKEY); + if (binding.key_expiration) { + sig.set_key_expiration(binding.key_expiration); + } + if (binding.key_flags) { + sig.set_key_flags(binding.key_flags); + } + /* calculate binding */ + pgp_key_flags_t realkf = (pgp_key_flags_t) binding.key_flags; + if (!realkf) { + realkf = pgp_pk_alg_capabilities(subsec.alg()); + } + sign_subkey_binding(subsec, sig, ctx, realkf & PGP_KF_SIGN); + /* add to the secret and public key */ + subsec.add_sig(sig); + subpub.add_sig(sig); +} + bool -pgp_key_t::refresh_data() +pgp_key_t::refresh_data(const rnp::SecurityContext &ctx) { if (!is_primary()) { RNP_LOG("key must be primary"); return false; } /* validate self-signatures if not done yet */ - validate_self_signatures(); + validate_self_signatures(ctx); /* key expiration */ expiration_ = 0; /* if we have direct-key signature, then it has higher priority */ @@ -2309,7 +2548,7 @@ } for (size_t i = 0; i < sig_count(); i++) { pgp_subsig_t &sig = get_sig(i); - /* if certification expires key then consider userid as expired too */ + /* consider userid as valid if it has at least one non-expired self-sig */ if (!sig.valid() || !sig.is_cert() || !is_signer(sig) || sig.expired()) { continue; } @@ -2325,31 +2564,21 @@ uid.valid = false; } } - /* primary userid: pick it only from valid ones */ + /* primary userid: use latest one which is not overriden by later non-primary selfsig */ uid0_set_ = false; - for (size_t i = 0; i < sig_count(); i++) { - pgp_subsig_t &sig = get_sig(i); - if (!sig.valid() || !sig.is_cert() || !is_signer(sig)) { - continue; - } - if ((sig.uid >= uid_count()) || !get_uid(sig.uid).valid) { - continue; - } - if (sig.sig.primary_uid()) { - uid0_ = sig.uid; - uid0_set_ = true; - break; - } + if (prisig && get_uid(prisig->uid).valid) { + uid0_ = prisig->uid; + uid0_set_ = true; } return true; } bool -pgp_key_t::refresh_data(pgp_key_t *primary) +pgp_key_t::refresh_data(pgp_key_t *primary, const rnp::SecurityContext &ctx) { /* validate self-signatures if not done yet */ if (primary) { - validate_self_signatures(*primary); + validate_self_signatures(*primary, ctx); } pgp_subsig_t *sig = latest_binding(primary); /* subkey expiration */ @@ -2551,3 +2780,20 @@ } return 8 * mpi_bytes(&dsa.q); } + +void +pgp_key_material_t::validate(rnp::SecurityContext &ctx, bool reset) +{ + if (!reset && validity.validated) { + return; + } + validity.reset(); + validity.valid = !validate_pgp_key_material(this, &ctx.rng); + validity.validated = true; +} + +bool +pgp_key_material_t::valid() const +{ + return validity.validated && validity.valid; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/pgp-key.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/pgp-key.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/pgp-key.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/pgp-key.h 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2017-2021 [Ribose Inc](https://www.ribose.com). * Copyright (c) 2009 The NetBSD Foundation, Inc. * All rights reserved. * @@ -62,6 +62,7 @@ #include "../librepgp/stream-packet.h" #include "crypto/symmetric.h" #include "types.h" +#include "sec_profile.hpp" /** pgp_rawpacket_t */ typedef struct pgp_rawpacket_t { @@ -79,17 +80,6 @@ void write(pgp_dest_t &dst) const; } pgp_rawpacket_t; -/* validity information for the signature/key/userid */ -typedef struct pgp_validity_t { - bool validated{}; /* item was validated */ - bool valid{}; /* item is valid by signature/key checks and calculations. - Still may be revoked or expired. */ - bool expired{}; /* item is expired */ - - void mark_valid(); - void reset(); -} pgp_validity_t; - /** information about the signature */ typedef struct pgp_subsig_t { uint32_t uid{}; /* index in userid array in key for certification sig */ @@ -171,16 +161,17 @@ void validate_primary(rnp_key_store_t &keyring); void merge_validity(const pgp_validity_t &src); uint64_t valid_till_common(bool expiry) const; - /** @brief helper function: write secret key data to the rawpkt, encrypting with password - */ - bool write_sec_rawpkt(pgp_key_pkt_t &seckey, const std::string &password); - bool write_sec_pgp(pgp_dest_t &dst, pgp_key_pkt_t &seckey, const std::string &password); + bool write_sec_pgp(pgp_dest_t & dst, + pgp_key_pkt_t & seckey, + const std::string &password, + rnp::RNG & rng); public: pgp_key_store_format_t format{}; /* the format of the key in packets[0] */ pgp_key_t() = default; pgp_key_t(const pgp_key_pkt_t &pkt); + pgp_key_t(const pgp_key_pkt_t &pkt, pgp_key_t &primary); pgp_key_t(const pgp_key_t &src, bool pubonly = false); pgp_key_t(const pgp_transferable_key_t &src); pgp_key_t(const pgp_transferable_subkey_t &src, pgp_key_t *primary); @@ -215,7 +206,7 @@ pgp_key_pkt_t & pkt(); void set_pkt(const pgp_key_pkt_t &pkt); - const pgp_key_material_t &material() const; + pgp_key_material_t &material(); pgp_pubkey_alg_t alg() const; pgp_curve_t curve() const; @@ -286,15 +277,18 @@ pgp_rawpacket_t & rawpkt(); const pgp_rawpacket_t &rawpkt() const; void set_rawpkt(const pgp_rawpacket_t &src); + /** @brief write secret key data to the rawpkt, optionally encrypting with password */ + bool write_sec_rawpkt(pgp_key_pkt_t &seckey, const std::string &password, rnp::RNG &rng); /** @brief Unlock a key, i.e. decrypt its secret data so it can be used for - *signing/decryption. Note: Key locking does not apply to unprotected keys. + * signing/decryption. + * Note: Key locking does not apply to unprotected keys. * - * @param pass_provider the password provider that may be used - * to unlock the key, if necessary + * @param pass_provider the password provider that may be used to unlock the key + * @param op operation for which secret key should be unloacked * @return true if the key was unlocked, false otherwise **/ - bool unlock(const pgp_password_provider_t &provider); + bool unlock(const pgp_password_provider_t &provider, pgp_op_t op = PGP_OP_UNLOCK); /** @brief Lock a key, i.e. cleanup decrypted secret data. * Note: Key locking does not apply to unprotected keys. * @@ -305,13 +299,15 @@ /** @brief Add protection to an unlocked key, i.e. encrypt its secret data with specified * parameters. */ bool protect(const rnp_key_protection_params_t &protection, - const pgp_password_provider_t & password_provider); + const pgp_password_provider_t & password_provider, + rnp::RNG & rng); /** @brief Add/change protection of a key */ bool protect(pgp_key_pkt_t & decrypted, const rnp_key_protection_params_t &protection, - const std::string & new_password); + const std::string & new_password, + rnp::RNG & rng); /** @brief Remove protection from a key, i.e. leave secret fields unencrypted */ - bool unprotect(const pgp_password_provider_t &password_provider); + bool unprotect(const pgp_password_provider_t &password_provider, rnp::RNG &rng); /** @brief Write key's packets to the output. */ void write(pgp_dest_t &dst) const; @@ -381,33 +377,212 @@ * * @param key key or subkey to which signature belongs. * @param sig signature to validate. + * @param ctx Populated security context. + */ + void validate_sig(const pgp_key_t & key, + pgp_subsig_t & sig, + const rnp::SecurityContext &ctx) const noexcept; + + /** + * @brief Validate signature, assuming that 'this' is a signing key. + * + * @param sinfo populated signature info. Validation results will be stored here. + * @param hash hash, feed with all signed data except signature trailer. + * @param ctx Populated security context. + */ + void validate_sig(pgp_signature_info_t & sinfo, + rnp::Hash & hash, + const rnp::SecurityContext &ctx) const noexcept; + + /** + * @brief Validate certification. + * + * @param sinfo populated signature info. Validation results will be stored here. + * @param key key packet to which certification belongs. + * @param uid userid which is bound by certification to the key packet. + */ + void validate_cert(pgp_signature_info_t & sinfo, + const pgp_key_pkt_t & key, + const pgp_userid_pkt_t & uid, + const rnp::SecurityContext &ctx) const; + + /** + * @brief Validate subkey binding. + * + * @param sinfo populated signature info. Validation results will be stored here. + * @param subkey subkey packet. */ - void validate_sig(const pgp_key_t &key, pgp_subsig_t &sig) const; - void validate_self_signatures(); - void validate_self_signatures(pgp_key_t &primary); + void validate_binding(pgp_signature_info_t & sinfo, + const pgp_key_t & subkey, + const rnp::SecurityContext &ctx) const; + + /** + * @brief Validate subkey revocation. + * + * @param sinfo populated signature info. Validation results will be stored here. + * @param subkey subkey packet. + */ + void validate_sub_rev(pgp_signature_info_t & sinfo, + const pgp_key_pkt_t & subkey, + const rnp::SecurityContext &ctx) const; + + /** + * @brief Validate direct-key signature. + * + * @param sinfo populated signature info. Validation results will be stored here. + */ + void validate_direct(pgp_signature_info_t &sinfo, const rnp::SecurityContext &ctx) const; + + void validate_self_signatures(const rnp::SecurityContext &ctx); + void validate_self_signatures(pgp_key_t &primary, const rnp::SecurityContext &ctx); void validate(rnp_key_store_t &keyring); - void validate_subkey(pgp_key_t *primary = NULL); + void validate_subkey(pgp_key_t *primary, const rnp::SecurityContext &ctx); void revalidate(rnp_key_store_t &keyring); void mark_valid(); + /** + * @brief Fill common signature parameters, assuming that current key is a signing one. + * @param sig signature to init. + * @param hash hash algorithm to use (may be changed if it is not suitable for public key + * algorithm). + */ + void sign_init(pgp_signature_t &sig, pgp_hash_alg_t hash) const; + /** + * @brief Calculate a certification and fill signature material. + * Note: secret key must be unlocked before calling this function. + * + * @param key key packet to sign. May be both public and secret. Could be signing key's + * packet for self-signature, or any other one for cross-key certification. + * @param uid uid to certify. + * @param sig signature, pre-populated with all of the required data, except the + * signature material. + */ + void sign_cert(const pgp_key_pkt_t & key, + const pgp_userid_pkt_t &uid, + pgp_signature_t & sig, + rnp::SecurityContext & ctx); + + /** + * @brief Calculate direct-key signature. + * Note: secret key must be unlocked before calling this function. + * + * @param key key packet to sign. May be both public and secret. + * @param sig signature, pre-populated with all of the required data, except the + * signature material. + */ + void sign_direct(const pgp_key_pkt_t & key, + pgp_signature_t & sig, + rnp::SecurityContext &ctx); + + /** + * @brief Calculate subkey or primary key binding. + * Note: this will not embed primary key binding for the signing subkey, it should + * be added by the caller. + * + * @param key subkey or primary key packet, may be both public or secret. + * @param sig signature, pre-populated with all of the required data, except the + * signature material. + */ + void sign_binding(const pgp_key_pkt_t & key, + pgp_signature_t & sig, + rnp::SecurityContext &ctx); + + /** + * @brief Calculate subkey binding. + * Note: secret key must be unlocked before calling this function. If subsign is + * true then subkey must be secret and unlocked as well so function can calculate + * primary key binding. + * + * @param sub subkey to bind to the primary key. If subsign is true then must be unlocked + * secret key. + * @param sig signature, pre-populated with all of the required data, except the + * signature material. + */ + void sign_subkey_binding(pgp_key_t & sub, + pgp_signature_t & sig, + rnp::SecurityContext &ctx, + bool subsign = false); + + /** + * @brief Generate key or subkey revocation signature. + * + * @param revoke revocation information. + * @param key key or subkey packet to revoke. + * @param sig object to store revocation signature. Will be populated in method call. + */ + void gen_revocation(const pgp_revoke_t & revoke, + pgp_hash_alg_t hash, + const pgp_key_pkt_t & key, + pgp_signature_t & sig, + rnp::SecurityContext &ctx); + + /** + * @brief Add and certify userid. + * Note: secret key must be unlocked before calling this function. + * + * @param cert certification and userid parameters. + * @param hash hash algorithm to use during signing. See sign_init() for more details. + * @param ctx security context. + * @param pubkey if non-NULL then userid and certification will be added to this key as + * well. + */ + void add_uid_cert(rnp_selfsig_cert_info_t &cert, + pgp_hash_alg_t hash, + rnp::SecurityContext & ctx, + pgp_key_t * pubkey = nullptr); + + /** + * @brief Calculate and add subkey binding signature. + * Note: must be called on the unlocked secret primary key. Calculated signature is + * added to the subkey. + * + * @param subsec secret subkey. + * @param subpub subkey's public part (so signature is added to both). + * @param binding information about subkey to put to the signature. + * @param hash hash algorithm to use (may be adjusted according to key and subkey + * algorithms) + */ + void add_sub_binding(pgp_key_t & subsec, + pgp_key_t & subpub, + const rnp_selfsig_binding_info_t &binding, + pgp_hash_alg_t hash, + rnp::SecurityContext & ctx); /** @brief Refresh internal fields after primary key is updated */ - bool refresh_data(); + bool refresh_data(const rnp::SecurityContext &ctx); /** @brief Refresh internal fields after subkey is updated */ - bool refresh_data(pgp_key_t *primary); + bool refresh_data(pgp_key_t *primary, const rnp::SecurityContext &ctx); /** @brief Merge primary key with the src, i.e. add all new userids/signatures/subkeys */ bool merge(const pgp_key_t &src); /** @brief Merge subkey with the source, i.e. add all new signatures */ bool merge(const pgp_key_t &src, pgp_key_t *primary); }; -pgp_key_pkt_t *pgp_decrypt_seckey_pgp(const uint8_t *, - size_t, - const pgp_key_pkt_t *, - const char *); - -pgp_key_pkt_t *pgp_decrypt_seckey(const pgp_key_t *, - const pgp_password_provider_t *, - const pgp_password_ctx_t *); +namespace rnp { +class KeyLocker { + bool lock_; + pgp_key_t &key_; + + public: + KeyLocker(pgp_key_t &key) : lock_(key.is_locked()), key_(key) + { + } + + ~KeyLocker() + { + if (lock_ && !key_.is_locked()) { + key_.lock(); + } + } +}; +}; // namespace rnp + +pgp_key_pkt_t *pgp_decrypt_seckey_pgp(const pgp_rawpacket_t &raw, + const pgp_key_pkt_t & key, + const char * password); + +pgp_key_pkt_t *pgp_decrypt_seckey(const pgp_key_t &, + const pgp_password_provider_t &, + const pgp_password_ctx_t &); /** * @brief Get the signer's key for signature @@ -433,29 +608,18 @@ pgp_key_flags_t pgp_pk_alg_capabilities(pgp_pubkey_alg_t alg); -/** add a new certified userid to a key - * - * @param key - * @param seckey the decrypted seckey for signing - * @param hash_alg the hash algorithm to be used for the signature - * @param cert the self-signature information - * @return true if the userid was added, false otherwise - */ -bool pgp_key_add_userid_certified(pgp_key_t * key, - const pgp_key_pkt_t * seckey, - pgp_hash_alg_t hash_alg, - rnp_selfsig_cert_info_t *cert); - bool pgp_key_set_expiration(pgp_key_t * key, pgp_key_t * signer, uint32_t expiry, - const pgp_password_provider_t &prov); + const pgp_password_provider_t &prov, + rnp::SecurityContext & ctx); bool pgp_subkey_set_expiration(pgp_key_t * sub, pgp_key_t * primsec, pgp_key_t * secsub, uint32_t expiry, - const pgp_password_provider_t &prov); + const pgp_password_provider_t &prov, + rnp::SecurityContext & ctx); /** find a key suitable for a particular operation * diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/rnp.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/rnp.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/rnp.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/rnp.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017-2020, Ribose Inc. + * Copyright (c) 2017-2021, Ribose Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,7 +55,8 @@ #include #include #include "utils.h" -#include "json_utils.h" +#include "str-utils.h" +#include "json-utils.h" #include "version.h" #include "ffi-priv-types.h" #include "file-utils.h" @@ -105,9 +106,7 @@ break; } if (!key && ffi->getkeycb && try_key_provider) { - char identifier[1 + MAX(MAX(MAX(PGP_KEY_ID_SIZE * 2, PGP_KEY_GRIP_SIZE), - PGP_FINGERPRINT_SIZE * 2), - MAX_ID_LENGTH)]; + char identifier[RNP_LOCATOR_MAX_SIZE]; const char *identifier_type = NULL; if (locator_to_str(search, &identifier_type, identifier, sizeof(identifier))) { @@ -133,27 +132,28 @@ static void rnp_ctx_init_ffi(rnp_ctx_t &ctx, rnp_ffi_t ffi) { - ctx.rng = &ffi->rng; + ctx.ctx = &ffi->context; ctx.ealg = DEFAULT_PGP_SYMM_ALG; } -static const pgp_map_t sig_type_map[] = {{PGP_SIG_BINARY, "binary"}, - {PGP_SIG_TEXT, "text"}, - {PGP_SIG_STANDALONE, "standalone"}, - {PGP_CERT_GENERIC, "certification (generic)"}, - {PGP_CERT_PERSONA, "certification (persona)"}, - {PGP_CERT_CASUAL, "certification (casual)"}, - {PGP_CERT_POSITIVE, "certification (positive)"}, - {PGP_SIG_SUBKEY, "subkey binding"}, - {PGP_SIG_PRIMARY, "primary key binding"}, - {PGP_SIG_DIRECT, "direct"}, - {PGP_SIG_REV_KEY, "key revocation"}, - {PGP_SIG_REV_SUBKEY, "subkey revocation"}, - {PGP_SIG_REV_CERT, "certification revocation"}, - {PGP_SIG_TIMESTAMP, "timestamp"}, - {PGP_SIG_3RD_PARTY, "third-party"}}; +static const id_str_pair sig_type_map[] = {{PGP_SIG_BINARY, "binary"}, + {PGP_SIG_TEXT, "text"}, + {PGP_SIG_STANDALONE, "standalone"}, + {PGP_CERT_GENERIC, "certification (generic)"}, + {PGP_CERT_PERSONA, "certification (persona)"}, + {PGP_CERT_CASUAL, "certification (casual)"}, + {PGP_CERT_POSITIVE, "certification (positive)"}, + {PGP_SIG_SUBKEY, "subkey binding"}, + {PGP_SIG_PRIMARY, "primary key binding"}, + {PGP_SIG_DIRECT, "direct"}, + {PGP_SIG_REV_KEY, "key revocation"}, + {PGP_SIG_REV_SUBKEY, "subkey revocation"}, + {PGP_SIG_REV_CERT, "certification revocation"}, + {PGP_SIG_TIMESTAMP, "timestamp"}, + {PGP_SIG_3RD_PARTY, "third-party"}, + {0, NULL}}; -static const pgp_map_t pubkey_alg_map[] = { +static const id_str_pair pubkey_alg_map[] = { {PGP_PKA_RSA, RNP_ALGNAME_RSA}, {PGP_PKA_RSA_ENCRYPT_ONLY, RNP_ALGNAME_RSA}, {PGP_PKA_RSA_SIGN_ONLY, RNP_ALGNAME_RSA}, @@ -163,93 +163,112 @@ {PGP_PKA_ECDH, RNP_ALGNAME_ECDH}, {PGP_PKA_ECDSA, RNP_ALGNAME_ECDSA}, {PGP_PKA_EDDSA, RNP_ALGNAME_EDDSA}, - {PGP_PKA_SM2, RNP_ALGNAME_SM2}}; + {PGP_PKA_SM2, RNP_ALGNAME_SM2}, + {0, NULL}}; -static const pgp_map_t symm_alg_map[] = {{PGP_SA_IDEA, RNP_ALGNAME_IDEA}, - {PGP_SA_TRIPLEDES, RNP_ALGNAME_TRIPLEDES}, - {PGP_SA_CAST5, RNP_ALGNAME_CAST5}, - {PGP_SA_BLOWFISH, RNP_ALGNAME_BLOWFISH}, - {PGP_SA_AES_128, RNP_ALGNAME_AES_128}, - {PGP_SA_AES_192, RNP_ALGNAME_AES_192}, - {PGP_SA_AES_256, RNP_ALGNAME_AES_256}, - {PGP_SA_TWOFISH, RNP_ALGNAME_TWOFISH}, - {PGP_SA_CAMELLIA_128, RNP_ALGNAME_CAMELLIA_128}, - {PGP_SA_CAMELLIA_192, RNP_ALGNAME_CAMELLIA_192}, - {PGP_SA_CAMELLIA_256, RNP_ALGNAME_CAMELLIA_256}, - {PGP_SA_SM4, RNP_ALGNAME_SM4}}; - -static const pgp_map_t aead_alg_map[] = { - {PGP_AEAD_NONE, "None"}, {PGP_AEAD_EAX, "EAX"}, {PGP_AEAD_OCB, "OCB"}}; - -static const pgp_map_t cipher_mode_map[] = { - {PGP_CIPHER_MODE_CFB, "CFB"}, {PGP_CIPHER_MODE_CBC, "CBC"}, {PGP_CIPHER_MODE_OCB, "OCB"}}; - -static const pgp_map_t compress_alg_map[] = {{PGP_C_NONE, "Uncompressed"}, - {PGP_C_ZIP, "ZIP"}, - {PGP_C_ZLIB, "ZLIB"}, - {PGP_C_BZIP2, "BZip2"}}; - -static const pgp_map_t hash_alg_map[] = {{PGP_HASH_MD5, RNP_ALGNAME_MD5}, - {PGP_HASH_SHA1, RNP_ALGNAME_SHA1}, - {PGP_HASH_RIPEMD, RNP_ALGNAME_RIPEMD160}, - {PGP_HASH_SHA256, RNP_ALGNAME_SHA256}, - {PGP_HASH_SHA384, RNP_ALGNAME_SHA384}, - {PGP_HASH_SHA512, RNP_ALGNAME_SHA512}, - {PGP_HASH_SHA224, RNP_ALGNAME_SHA224}, - {PGP_HASH_SHA3_256, RNP_ALGNAME_SHA3_256}, - {PGP_HASH_SHA3_512, RNP_ALGNAME_SHA3_512}, - {PGP_HASH_SM3, RNP_ALGNAME_SM3}}; +static const id_str_pair symm_alg_map[] = {{PGP_SA_IDEA, RNP_ALGNAME_IDEA}, + {PGP_SA_TRIPLEDES, RNP_ALGNAME_TRIPLEDES}, + {PGP_SA_CAST5, RNP_ALGNAME_CAST5}, + {PGP_SA_BLOWFISH, RNP_ALGNAME_BLOWFISH}, + {PGP_SA_AES_128, RNP_ALGNAME_AES_128}, + {PGP_SA_AES_192, RNP_ALGNAME_AES_192}, + {PGP_SA_AES_256, RNP_ALGNAME_AES_256}, + {PGP_SA_TWOFISH, RNP_ALGNAME_TWOFISH}, + {PGP_SA_CAMELLIA_128, RNP_ALGNAME_CAMELLIA_128}, + {PGP_SA_CAMELLIA_192, RNP_ALGNAME_CAMELLIA_192}, + {PGP_SA_CAMELLIA_256, RNP_ALGNAME_CAMELLIA_256}, + {PGP_SA_SM4, RNP_ALGNAME_SM4}, + {0, NULL}}; + +static const id_str_pair aead_alg_map[] = { + {PGP_AEAD_NONE, "None"}, {PGP_AEAD_EAX, "EAX"}, {PGP_AEAD_OCB, "OCB"}, {0, NULL}}; + +static const id_str_pair cipher_mode_map[] = {{PGP_CIPHER_MODE_CFB, "CFB"}, + {PGP_CIPHER_MODE_CBC, "CBC"}, + {PGP_CIPHER_MODE_OCB, "OCB"}, + {0, NULL}}; + +static const id_str_pair compress_alg_map[] = {{PGP_C_NONE, "Uncompressed"}, + {PGP_C_ZIP, "ZIP"}, + {PGP_C_ZLIB, "ZLIB"}, + {PGP_C_BZIP2, "BZip2"}, + {0, NULL}}; + +static const id_str_pair hash_alg_map[] = {{PGP_HASH_MD5, RNP_ALGNAME_MD5}, + {PGP_HASH_SHA1, RNP_ALGNAME_SHA1}, + {PGP_HASH_RIPEMD, RNP_ALGNAME_RIPEMD160}, + {PGP_HASH_SHA256, RNP_ALGNAME_SHA256}, + {PGP_HASH_SHA384, RNP_ALGNAME_SHA384}, + {PGP_HASH_SHA512, RNP_ALGNAME_SHA512}, + {PGP_HASH_SHA224, RNP_ALGNAME_SHA224}, + {PGP_HASH_SHA3_256, RNP_ALGNAME_SHA3_256}, + {PGP_HASH_SHA3_512, RNP_ALGNAME_SHA3_512}, + {PGP_HASH_SM3, RNP_ALGNAME_SM3}, + {0, NULL}}; -static const pgp_map_t s2k_type_map[] = { +static const id_str_pair s2k_type_map[] = { {PGP_S2KS_SIMPLE, "Simple"}, {PGP_S2KS_SALTED, "Salted"}, - {PGP_S2KS_ITERATED_AND_SALTED, "Iterated and salted"}}; + {PGP_S2KS_ITERATED_AND_SALTED, "Iterated and salted"}, + {0, NULL}}; -static const pgp_bit_map_t key_usage_map[] = {{PGP_KF_SIGN, "sign"}, - {PGP_KF_CERTIFY, "certify"}, - {PGP_KF_ENCRYPT, "encrypt"}, - {PGP_KF_AUTH, "authenticate"}}; - -static const pgp_bit_map_t key_flags_map[] = {{PGP_KF_SPLIT, "split"}, - {PGP_KF_SHARED, "shared"}}; - -static const pgp_map_t identifier_type_map[] = {{PGP_KEY_SEARCH_USERID, "userid"}, - {PGP_KEY_SEARCH_KEYID, "keyid"}, - {PGP_KEY_SEARCH_FINGERPRINT, "fingerprint"}, - {PGP_KEY_SEARCH_GRIP, "grip"}}; - -static const pgp_map_t key_server_prefs_map[] = {{PGP_KEY_SERVER_NO_MODIFY, "no-modify"}}; - -static const pgp_map_t armor_type_map[] = {{PGP_ARMORED_MESSAGE, "message"}, - {PGP_ARMORED_PUBLIC_KEY, "public key"}, - {PGP_ARMORED_SECRET_KEY, "secret key"}, - {PGP_ARMORED_SIGNATURE, "signature"}, - {PGP_ARMORED_CLEARTEXT, "cleartext"}}; +static const id_str_pair key_usage_map[] = { + {PGP_KF_SIGN, "sign"}, + {PGP_KF_CERTIFY, "certify"}, + {PGP_KF_ENCRYPT, "encrypt"}, + {PGP_KF_AUTH, "authenticate"}, + {0, NULL}, +}; + +static const id_str_pair key_flags_map[] = { + {PGP_KF_SPLIT, "split"}, + {PGP_KF_SHARED, "shared"}, + {0, NULL}, +}; + +static const id_str_pair identifier_type_map[] = {{PGP_KEY_SEARCH_USERID, "userid"}, + {PGP_KEY_SEARCH_KEYID, "keyid"}, + {PGP_KEY_SEARCH_FINGERPRINT, "fingerprint"}, + {PGP_KEY_SEARCH_GRIP, "grip"}, + {0, NULL}}; + +static const id_str_pair key_server_prefs_map[] = {{PGP_KEY_SERVER_NO_MODIFY, "no-modify"}, + {0, NULL}}; + +static const id_str_pair armor_type_map[] = {{PGP_ARMORED_MESSAGE, "message"}, + {PGP_ARMORED_PUBLIC_KEY, "public key"}, + {PGP_ARMORED_SECRET_KEY, "secret key"}, + {PGP_ARMORED_SIGNATURE, "signature"}, + {PGP_ARMORED_CLEARTEXT, "cleartext"}, + {0, NULL}}; -static const pgp_map_t key_import_status_map[] = { +static const id_str_pair key_import_status_map[] = { {PGP_KEY_IMPORT_STATUS_UNKNOWN, "unknown"}, {PGP_KEY_IMPORT_STATUS_UNCHANGED, "unchanged"}, {PGP_KEY_IMPORT_STATUS_UPDATED, "updated"}, - {PGP_KEY_IMPORT_STATUS_NEW, "new"}}; + {PGP_KEY_IMPORT_STATUS_NEW, "new"}, + {0, NULL}}; -static const pgp_map_t sig_import_status_map[] = { +static const id_str_pair sig_import_status_map[] = { {PGP_SIG_IMPORT_STATUS_UNKNOWN, "unknown"}, {PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY, "unknown key"}, {PGP_SIG_IMPORT_STATUS_UNCHANGED, "unchanged"}, - {PGP_SIG_IMPORT_STATUS_NEW, "new"}}; + {PGP_SIG_IMPORT_STATUS_NEW, "new"}, + {0, NULL}}; -static const pgp_map_t revocation_code_map[] = { +static const id_str_pair revocation_code_map[] = { {PGP_REVOCATION_NO_REASON, "no"}, {PGP_REVOCATION_SUPERSEDED, "superseded"}, {PGP_REVOCATION_COMPROMISED, "compromised"}, {PGP_REVOCATION_RETIRED, "retired"}, - {PGP_REVOCATION_NO_LONGER_VALID, "no longer valid"}}; + {PGP_REVOCATION_NO_LONGER_VALID, "no longer valid"}, + {0, NULL}}; static bool curve_str_to_type(const char *str, pgp_curve_t *value) { *value = find_curve_by_name(str); - return *value != PGP_CURVE_MAX; + return curve_supported(*value); } static bool @@ -266,12 +285,21 @@ static bool str_to_cipher(const char *str, pgp_symm_alg_t *cipher) { - pgp_symm_alg_t alg = PGP_SA_UNKNOWN; - ARRAY_LOOKUP_BY_STRCASE(symm_alg_map, string, type, str, alg); + auto alg = + static_cast(id_str_pair::lookup(symm_alg_map, str, PGP_SA_UNKNOWN)); if (alg == PGP_SA_UNKNOWN) { return false; } - +#if !defined(ENABLE_SM2) + if (alg == PGP_SA_SM4) { + return false; + } +#endif +#if !defined(ENABLE_TWOFISH) + if (alg == PGP_SA_TWOFISH) { + return false; + } +#endif *cipher = alg; return true; } @@ -279,12 +307,16 @@ static bool str_to_hash_alg(const char *str, pgp_hash_alg_t *hash_alg) { - pgp_hash_alg_t alg = PGP_HASH_UNKNOWN; - ARRAY_LOOKUP_BY_STRCASE(hash_alg_map, string, type, str, alg); + auto alg = + static_cast(id_str_pair::lookup(hash_alg_map, str, PGP_HASH_UNKNOWN)); if (alg == PGP_HASH_UNKNOWN) { return false; } - +#if !defined(ENABLE_SM2) + if (alg == PGP_HASH_SM3) { + return false; + } +#endif *hash_alg = alg; return true; } @@ -292,12 +324,16 @@ static bool str_to_aead_alg(const char *str, pgp_aead_alg_t *aead_alg) { - pgp_aead_alg_t alg = PGP_AEAD_UNKNOWN; - ARRAY_LOOKUP_BY_STRCASE(aead_alg_map, string, type, str, alg); + pgp_aead_alg_t alg = + static_cast(id_str_pair::lookup(aead_alg_map, str, PGP_AEAD_UNKNOWN)); if (alg == PGP_AEAD_UNKNOWN) { return false; } - +#if !defined(ENABLE_AEAD) + if (alg != PGP_AEAD_NONE) { + return false; + } +#endif *aead_alg = alg; return true; } @@ -305,8 +341,8 @@ static bool str_to_compression_alg(const char *str, pgp_compression_type_t *zalg) { - pgp_compression_type_t alg = PGP_C_UNKNOWN; - ARRAY_LOOKUP_BY_STRCASE(compress_alg_map, string, type, str, alg); + pgp_compression_type_t alg = static_cast( + id_str_pair::lookup(compress_alg_map, str, PGP_C_UNKNOWN)); if (alg == PGP_C_UNKNOWN) { return false; } @@ -317,9 +353,9 @@ static bool str_to_revocation_type(const char *str, pgp_revocation_type_t *code) { - pgp_revocation_type_t rev = PGP_REVOCATION_NO_REASON; - ARRAY_LOOKUP_BY_STRCASE(revocation_code_map, string, type, str, rev); - if ((rev == PGP_REVOCATION_NO_REASON) && rnp_strcasecmp(str, "no")) { + pgp_revocation_type_t rev = static_cast( + id_str_pair::lookup(revocation_code_map, str, PGP_REVOCATION_NO_REASON)); + if ((rev == PGP_REVOCATION_NO_REASON) && !rnp::str_case_eq(str, "no")) { return false; } *code = rev; @@ -329,8 +365,8 @@ static bool str_to_cipher_mode(const char *str, pgp_cipher_mode_t *mode) { - pgp_cipher_mode_t c_mode = PGP_CIPHER_MODE_NONE; - ARRAY_LOOKUP_BY_STRCASE(cipher_mode_map, string, type, str, c_mode); + pgp_cipher_mode_t c_mode = static_cast( + id_str_pair::lookup(cipher_mode_map, str, PGP_CIPHER_MODE_NONE)); if (c_mode == PGP_CIPHER_MODE_NONE) { return false; } @@ -342,12 +378,16 @@ static bool str_to_pubkey_alg(const char *str, pgp_pubkey_alg_t *pub_alg) { - pgp_pubkey_alg_t alg = PGP_PKA_NOTHING; - ARRAY_LOOKUP_BY_STRCASE(pubkey_alg_map, string, type, str, alg); + pgp_pubkey_alg_t alg = + static_cast(id_str_pair::lookup(pubkey_alg_map, str, PGP_PKA_NOTHING)); if (alg == PGP_PKA_NOTHING) { return false; } - +#if !defined(ENABLE_SM2) + if (alg == PGP_PKA_SM2) { + return false; + } +#endif *pub_alg = alg; return true; } @@ -355,8 +395,7 @@ static bool str_to_key_flag(const char *str, uint8_t *flag) { - uint8_t _flag = 0; - ARRAY_LOOKUP_BY_STRCASE(key_usage_map, string, mask, str, _flag); + uint8_t _flag = id_str_pair::lookup(key_usage_map, str); if (!_flag) { return false; } @@ -399,15 +438,9 @@ } static rnp_result_t -get_map_value(const pgp_map_t *map, size_t msize, int val, char **res) +get_map_value(const id_str_pair *map, int val, char **res) { - const char *str = NULL; - for (size_t i = 0; i < msize; i++) { - if (map[i].type == val) { - str = map[i].string; - break; - } - } + const char *str = id_str_pair::lookup(map, val, NULL); if (!str) { return RNP_ERROR_BAD_PARAMETERS; } @@ -463,12 +496,36 @@ #define FFI_GUARD FFI_GUARD_FP((stderr)) +rnp_ffi_st::rnp_ffi_st(pgp_key_store_format_t pub_fmt, pgp_key_store_format_t sec_fmt) +{ + errs = stderr; + pubring = new rnp_key_store_t(pub_fmt, "", context); + secring = new rnp_key_store_t(sec_fmt, "", context); + getkeycb = NULL; + getkeycb_ctx = NULL; + getpasscb = NULL; + getpasscb_ctx = NULL; + key_provider.callback = ffi_key_provider; + key_provider.userdata = this; + pass_provider.callback = rnp_password_cb_bounce; + pass_provider.userdata = this; +} + +rnp::RNG & +rnp_ffi_st::rng() noexcept +{ + return context.rng; +} + +rnp::SecurityProfile & +rnp_ffi_st::profile() noexcept +{ + return context.profile; +} + rnp_result_t rnp_ffi_create(rnp_ffi_t *ffi, const char *pub_format, const char *sec_format) try { - struct rnp_ffi_st *ob = NULL; - rnp_result_t ret = RNP_ERROR_GENERIC; - // checks if (!ffi || !pub_format || !sec_format) { return RNP_ERROR_NULL_POINTER; @@ -481,38 +538,9 @@ return RNP_ERROR_BAD_PARAMETERS; } - ob = (rnp_ffi_st *) calloc(1, sizeof(struct rnp_ffi_st)); - if (!ob) { - return RNP_ERROR_OUT_OF_MEMORY; - } - // default to all stderr - ob->errs = stderr; - try { - ob->pubring = new rnp_key_store_t(pub_ks_format, ""); - ob->secring = new rnp_key_store_t(sec_ks_format, ""); - } catch (const std::exception &e) { - FFI_LOG(ob, "%s", e.what()); - ret = RNP_ERROR_OUT_OF_MEMORY; - goto done; - } - - ob->key_provider.callback = ffi_key_provider; - ob->key_provider.userdata = ob; - ob->pass_provider.callback = rnp_password_cb_bounce; - ob->pass_provider.userdata = ob; - if (!rng_init(&ob->rng, RNG_DRBG)) { - ret = RNP_ERROR_RNG; - goto done; - } - - ret = RNP_SUCCESS; -done: - if (ret) { - rnp_ffi_destroy(ob); - ob = NULL; - } + struct rnp_ffi_st *ob = new rnp_ffi_st(pub_ks_format, sec_ks_format); *ffi = ob; - return ret; + return RNP_SUCCESS; } FFI_GUARD @@ -531,15 +559,18 @@ *fp = NULL; } +rnp_ffi_st::~rnp_ffi_st() +{ + close_io_file(&errs); + delete pubring; + delete secring; +} + rnp_result_t rnp_ffi_destroy(rnp_ffi_t ffi) try { if (ffi) { - close_io_file(&ffi->errs); - delete ffi->pubring; - delete ffi->secring; - rng_destroy(&ffi->rng); - free(ffi); + delete ffi; } return RNP_SUCCESS; } @@ -548,17 +579,14 @@ rnp_result_t rnp_ffi_set_log_fd(rnp_ffi_t ffi, int fd) try { - FILE *errs = NULL; - // checks if (!ffi) { return RNP_ERROR_NULL_POINTER; } // open - errs = fdopen(fd, "a"); + FILE *errs = fdopen(fd, "a"); if (!errs) { - close_io_file(&errs); return RNP_ERROR_ACCESS; } // close previous streams and replace them @@ -760,20 +788,23 @@ return RNP_VERSION_COMMIT_TIMESTAMP; } +#ifndef RNP_NO_DEPRECATED rnp_result_t rnp_enable_debug(const char *file) try { - return rnp_set_debug(file) ? RNP_SUCCESS : RNP_ERROR_GENERIC; + return RNP_SUCCESS; } FFI_GUARD +#endif +#ifndef RNP_NO_DEPRECATED rnp_result_t rnp_disable_debug() try { - rnp_clear_debug(); return RNP_SUCCESS; } FFI_GUARD +#endif rnp_result_t rnp_get_default_homedir(char **homedir) @@ -958,25 +989,25 @@ if (!type || !name || !supported) { return RNP_ERROR_NULL_POINTER; } - if (!rnp_strcasecmp(type, RNP_FEATURE_SYMM_ALG)) { + if (rnp::str_case_eq(type, RNP_FEATURE_SYMM_ALG)) { pgp_symm_alg_t alg = PGP_SA_UNKNOWN; *supported = str_to_cipher(name, &alg); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_AEAD_ALG)) { + } else if (rnp::str_case_eq(type, RNP_FEATURE_AEAD_ALG)) { pgp_aead_alg_t alg = PGP_AEAD_UNKNOWN; *supported = str_to_aead_alg(name, &alg); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_PROT_MODE)) { + } else if (rnp::str_case_eq(type, RNP_FEATURE_PROT_MODE)) { // for now we support only CFB for key encryption - *supported = rnp_strcasecmp(name, "CFB") == 0; - } else if (!rnp_strcasecmp(type, RNP_FEATURE_PK_ALG)) { + *supported = rnp::str_case_eq(name, "CFB"); + } else if (rnp::str_case_eq(type, RNP_FEATURE_PK_ALG)) { pgp_pubkey_alg_t alg = PGP_PKA_NOTHING; *supported = str_to_pubkey_alg(name, &alg); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_HASH_ALG)) { + } else if (rnp::str_case_eq(type, RNP_FEATURE_HASH_ALG)) { pgp_hash_alg_t alg = PGP_HASH_UNKNOWN; *supported = str_to_hash_alg(name, &alg); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_COMP_ALG)) { + } else if (rnp::str_case_eq(type, RNP_FEATURE_COMP_ALG)) { pgp_compression_type_t alg = PGP_C_UNKNOWN; *supported = str_to_compression_alg(name, &alg); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_CURVE)) { + } else if (rnp::str_case_eq(type, RNP_FEATURE_CURVE)) { pgp_curve_t curve = PGP_CURVE_UNKNOWN; *supported = curve_str_to_type(name, &curve); } else { @@ -987,19 +1018,15 @@ FFI_GUARD static rnp_result_t -json_array_add_map_str(json_object *arr, const pgp_map_t *map, int from, int to) +json_array_add_id_str(json_object *arr, const id_str_pair *map, int from, int to) { - while (map->string) { - if (map->type < from) { - map++; - continue; - } - if (!array_add_element_json(arr, json_object_new_string(map->string))) { + while (map->str && (map->id < from)) { + map++; + } + while (map->str && (map->id <= to)) { + if (!array_add_element_json(arr, json_object_new_string(map->str))) { return RNP_ERROR_OUT_OF_MEMORY; } - if (map->type >= to) { - break; - } map++; } return RNP_SUCCESS; @@ -1019,22 +1046,40 @@ rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; - if (!rnp_strcasecmp(type, RNP_FEATURE_SYMM_ALG)) { - ret = json_array_add_map_str(features, symm_alg_map, PGP_SA_IDEA, PGP_SA_SM4); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_AEAD_ALG)) { - ret = json_array_add_map_str(features, aead_alg_map, PGP_AEAD_EAX, PGP_AEAD_OCB); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_PROT_MODE)) { - ret = json_array_add_map_str( + if (rnp::str_case_eq(type, RNP_FEATURE_SYMM_ALG)) { + ret = json_array_add_id_str(features, symm_alg_map, PGP_SA_IDEA, PGP_SA_AES_256); +#if defined(ENABLE_TWOFISH) + ret = json_array_add_id_str(features, symm_alg_map, PGP_SA_TWOFISH, PGP_SA_TWOFISH); +#endif + ret = json_array_add_id_str( + features, symm_alg_map, PGP_SA_CAMELLIA_128, PGP_SA_CAMELLIA_256); +#if defined(ENABLE_SM2) + ret = json_array_add_id_str(features, symm_alg_map, PGP_SA_SM4, PGP_SA_SM4); +#endif + } else if (rnp::str_case_eq(type, RNP_FEATURE_AEAD_ALG)) { +#if defined(ENABLE_AEAD) + ret = json_array_add_id_str(features, aead_alg_map, PGP_AEAD_NONE, PGP_AEAD_OCB); +#else + ret = json_array_add_id_str(features, aead_alg_map, PGP_AEAD_NONE, PGP_AEAD_NONE); +#endif + } else if (rnp::str_case_eq(type, RNP_FEATURE_PROT_MODE)) { + ret = json_array_add_id_str( features, cipher_mode_map, PGP_CIPHER_MODE_CFB, PGP_CIPHER_MODE_CFB); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_PK_ALG)) { + } else if (rnp::str_case_eq(type, RNP_FEATURE_PK_ALG)) { // workaround to avoid duplicates, maybe there is a better solution - (void) json_array_add_map_str(features, pubkey_alg_map, PGP_PKA_RSA, PGP_PKA_RSA); - ret = json_array_add_map_str(features, pubkey_alg_map, PGP_PKA_DSA, PGP_PKA_SM2); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_HASH_ALG)) { - ret = json_array_add_map_str(features, hash_alg_map, PGP_HASH_MD5, PGP_HASH_SM3); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_COMP_ALG)) { - ret = json_array_add_map_str(features, compress_alg_map, PGP_C_NONE, PGP_C_BZIP2); - } else if (!rnp_strcasecmp(type, RNP_FEATURE_CURVE)) { + (void) json_array_add_id_str(features, pubkey_alg_map, PGP_PKA_RSA, PGP_PKA_RSA); + ret = json_array_add_id_str(features, pubkey_alg_map, PGP_PKA_DSA, PGP_PKA_EDDSA); +#if defined(ENABLE_SM2) + ret = json_array_add_id_str(features, pubkey_alg_map, PGP_PKA_SM2, PGP_PKA_SM2); +#endif + } else if (rnp::str_case_eq(type, RNP_FEATURE_HASH_ALG)) { + ret = json_array_add_id_str(features, hash_alg_map, PGP_HASH_MD5, PGP_HASH_SHA3_512); +#if defined(ENABLE_SM2) + ret = json_array_add_id_str(features, hash_alg_map, PGP_HASH_SM3, PGP_HASH_SM3); +#endif + } else if (rnp::str_case_eq(type, RNP_FEATURE_COMP_ALG)) { + ret = json_array_add_id_str(features, compress_alg_map, PGP_C_NONE, PGP_C_BZIP2); + } else if (rnp::str_case_eq(type, RNP_FEATURE_CURVE)) { for (pgp_curve_t curve = PGP_CURVE_NIST_P_256; curve < PGP_CURVE_MAX; curve = (pgp_curve_t)(curve + 1)) { const ec_curve_desc_t *desc = get_curve_desc(curve); @@ -1042,6 +1087,9 @@ ret = RNP_ERROR_BAD_STATE; goto done; } + if (!desc->supported) { + continue; + } if (!array_add_element_json(features, json_object_new_string(desc->pgp_name))) { ret = RNP_ERROR_OUT_OF_MEMORY; goto done; @@ -1069,6 +1117,185 @@ } FFI_GUARD +static bool +get_feature_sec_value( + rnp_ffi_t ffi, const char *stype, const char *sname, rnp::FeatureType &type, int &value) +{ + /* check type */ + if (!rnp::str_case_eq(stype, RNP_FEATURE_HASH_ALG)) { + FFI_LOG(ffi, "Unsupported feature type: %s", stype); + return false; + } + type = rnp::FeatureType::Hash; + /* check feature name */ + pgp_hash_alg_t alg = PGP_HASH_UNKNOWN; + if (sname && !str_to_hash_alg(sname, &alg)) { + FFI_LOG(ffi, "Unknown hash algorithm: %s", sname); + return false; + } + value = alg; + return true; +} + +static bool +get_feature_sec_level(rnp_ffi_t ffi, uint32_t flevel, rnp::SecurityLevel &level) +{ + switch (flevel) { + case RNP_SECURITY_PROHIBITED: + level = rnp::SecurityLevel::Disabled; + break; + case RNP_SECURITY_INSECURE: + level = rnp::SecurityLevel::Insecure; + break; + case RNP_SECURITY_DEFAULT: + level = rnp::SecurityLevel::Default; + break; + default: + FFI_LOG(ffi, "Invalid security level : %" PRIu32, flevel); + return false; + } + return true; +} + +rnp_result_t +rnp_add_security_rule(rnp_ffi_t ffi, + const char *type, + const char *name, + uint32_t flags, + uint64_t from, + uint32_t level) +try { + if (!ffi || !type || !name) { + return RNP_ERROR_NULL_POINTER; + } + /* convert values */ + rnp::FeatureType ftype; + int fvalue; + rnp::SecurityLevel sec_level; + if (!get_feature_sec_value(ffi, type, name, ftype, fvalue) || + !get_feature_sec_level(ffi, level, sec_level)) { + return RNP_ERROR_BAD_PARAMETERS; + } + /* check flags */ + bool rule_override = flags & RNP_SECURITY_OVERRIDE; + flags &= ~RNP_SECURITY_OVERRIDE; + if (flags) { + FFI_LOG(ffi, "Unknown flags: %" PRIu32, flags); + return RNP_ERROR_BAD_PARAMETERS; + } + /* add rule */ + rnp::SecurityRule newrule(ftype, fvalue, sec_level, from); + newrule.override = rule_override; + ffi->profile().add_rule(newrule); + return RNP_SUCCESS; +} +FFI_GUARD + +rnp_result_t +rnp_get_security_rule(rnp_ffi_t ffi, + const char *type, + const char *name, + uint64_t time, + uint32_t * flags, + uint64_t * from, + uint32_t * level) +try { + if (!ffi || !type || !name || !level) { + return RNP_ERROR_NULL_POINTER; + } + /* convert values */ + rnp::FeatureType ftype; + int fvalue; + if (!get_feature_sec_value(ffi, type, name, ftype, fvalue)) { + return RNP_ERROR_BAD_PARAMETERS; + } + /* init default rule */ + rnp::SecurityRule rule(ftype, fvalue, ffi->profile().def_level()); + /* check whether rule exists */ + if (ffi->profile().has_rule(ftype, fvalue, time)) { + rule = ffi->profile().get_rule(ftype, fvalue, time); + } + /* fill the results */ + if (flags) { + *flags = rule.override ? RNP_SECURITY_OVERRIDE : 0; + } + if (from) { + *from = rule.from; + } + switch (rule.level) { + case rnp::SecurityLevel::Disabled: + *level = RNP_SECURITY_PROHIBITED; + break; + case rnp::SecurityLevel::Insecure: + *level = RNP_SECURITY_INSECURE; + break; + case rnp::SecurityLevel::Default: + *level = RNP_SECURITY_DEFAULT; + break; + default: + FFI_LOG(ffi, "Invalid security level."); + return RNP_ERROR_BAD_STATE; + } + return RNP_SUCCESS; +} +FFI_GUARD + +rnp_result_t +rnp_remove_security_rule(rnp_ffi_t ffi, + const char *type, + const char *name, + uint32_t level, + uint32_t flags, + uint64_t from, + size_t * removed) +try { + if (!ffi) { + return RNP_ERROR_NULL_POINTER; + } + /* check flags */ + bool remove_all = flags & RNP_SECURITY_REMOVE_ALL; + flags &= ~RNP_SECURITY_REMOVE_ALL; + bool rule_override = flags & RNP_SECURITY_OVERRIDE; + flags &= ~RNP_SECURITY_OVERRIDE; + if (flags) { + FFI_LOG(ffi, "Unknown flags: %" PRIu32, flags); + return RNP_ERROR_BAD_PARAMETERS; + } + /* remove all rules */ + size_t rules = ffi->profile().size(); + if (!type) { + ffi->profile().clear_rules(); + goto success; + } + rnp::FeatureType ftype; + int fvalue; + rnp::SecurityLevel flevel; + if (!get_feature_sec_value(ffi, type, name, ftype, fvalue) || + !get_feature_sec_level(ffi, level, flevel)) { + return RNP_ERROR_BAD_PARAMETERS; + } + /* remove all rules for the specified type */ + if (!name) { + ffi->profile().clear_rules(ftype); + goto success; + } + if (remove_all) { + /* remove all rules for the specified type and name */ + ffi->profile().clear_rules(ftype, fvalue); + } else { + /* remove specific rule */ + rnp::SecurityRule rule(ftype, fvalue, flevel, from); + rule.override = rule_override; + ffi->profile().del_rule(rule); + } +success: + if (removed) { + *removed = rules - ffi->profile().size(); + } + return RNP_SUCCESS; +} +FFI_GUARD + rnp_result_t rnp_request_password(rnp_ffi_t ffi, rnp_key_handle_t key, const char *context, char **password) { @@ -1165,7 +1392,7 @@ // create a temporary key store to hold the keys try { - tmp_store = new rnp_key_store_t(format, ""); + tmp_store = new rnp_key_store_t(format, "", ffi->context); } catch (const std::invalid_argument &e) { FFI_LOG(ffi, "Failed to create key store of format: %d", (int) format); return RNP_ERROR_BAD_PARAMETERS; @@ -1361,9 +1588,7 @@ if (status == PGP_KEY_IMPORT_STATUS_UNKNOWN) { return "none"; } - const char *str = "none"; - ARRAY_LOOKUP_BY_ID(key_import_status_map, type, string, status, str); - return str; + return id_str_pair::lookup(key_import_status_map, status, "none"); } static rnp_result_t @@ -1433,7 +1658,7 @@ // load keys to temporary keystore. try { - tmp_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, ""); + tmp_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", ffi->context); } catch (const std::exception &e) { FFI_LOG(ffi, "Failed to create key store: %s.", e.what()); return RNP_ERROR_OUT_OF_MEMORY; @@ -1478,13 +1703,6 @@ if (!pub && key.is_public()) { continue; } - if (validate_pgp_key_material(&key.material(), &ffi->rng)) { - char hex[PGP_KEY_ID_SIZE * 2 + 1] = {0}; - rnp::hex_encode( - key.keyid().data(), key.keyid().size(), hex, sizeof(hex), rnp::HEX_LOWERCASE); - FFI_LOG(ffi, "warning! attempt to import key %s with invalid material.", hex); - continue; - } // if we got here then we add public key itself or public part of the secret key if (!rnp_key_store_import_key(ffi->pubring, &key, true, &pub_status)) { ret = RNP_ERROR_BAD_PARAMETERS; @@ -1536,9 +1754,7 @@ if (status == PGP_SIG_IMPORT_STATUS_UNKNOWN) { return "none"; } - const char *str = "none"; - ARRAY_LOOKUP_BY_ID(sig_import_status_map, type, string, status, str); - return str; + return id_str_pair::lookup(sig_import_status_map, status, "none"); } static rnp_result_t @@ -1663,7 +1879,7 @@ // create a temporary key store to hold the keys rnp_key_store_t *tmp_store = NULL; try { - tmp_store = new rnp_key_store_t(format, ""); + tmp_store = new rnp_key_store_t(format, "", ffi->context); } catch (const std::invalid_argument &e) { FFI_LOG(ffi, "Failed to create key store of format: %d", (int) format); return RNP_ERROR_BAD_PARAMETERS; @@ -2010,9 +2226,9 @@ } pgp_armored_msg_t msgtype = PGP_ARMORED_MESSAGE; if (type) { - msgtype = PGP_ARMORED_UNKNOWN; - ARRAY_LOOKUP_BY_STRCASE(armor_type_map, string, type, type, msgtype); - if (!msgtype) { + msgtype = static_cast( + id_str_pair::lookup(armor_type_map, type, PGP_ARMORED_UNKNOWN)); + if (msgtype == PGP_ARMORED_UNKNOWN) { RNP_LOG("Unsupported armor type: %s", type); return RNP_ERROR_BAD_PARAMETERS; } @@ -2191,10 +2407,10 @@ pgp_key_t *signkey = find_suitable_key( PGP_OP_SIGN, get_key_prefer_public(key), &key->ffi->key_provider, PGP_KF_SIGN); if (signkey && !signkey->is_secret()) { - pgp_key_request_ctx_t ctx = {.op = PGP_OP_SIGN, .secret = true}; - ctx.search.type = PGP_KEY_SEARCH_GRIP; - ctx.search.by.grip = signkey->grip(); - signkey = pgp_request_key(&key->ffi->key_provider, &ctx); + pgp_key_request_ctx_t keyctx = {.op = PGP_OP_SIGN, .secret = true}; + keyctx.search.type = PGP_KEY_SEARCH_GRIP; + keyctx.search.by.grip = signkey->grip(); + signkey = pgp_request_key(&key->ffi->key_provider, &keyctx); } if (!signkey) { return RNP_ERROR_NO_SUITABLE_KEY; @@ -2399,7 +2615,7 @@ } pgp_symm_alg_t symm_alg = PGP_SA_UNKNOWN; if (!str_to_cipher(s2k_cipher, &symm_alg)) { - FFI_LOG(op->ffi, "Invalid cipher: %s", s2k_hash); + FFI_LOG(op->ffi, "Invalid cipher: %s", s2k_cipher); return RNP_ERROR_BAD_PARAMETERS; } try { @@ -2436,7 +2652,7 @@ rnp_op_encrypt_set_cipher(rnp_op_encrypt_t op, const char *cipher) try { // checks - if (!op) { + if (!op || !cipher) { return RNP_ERROR_NULL_POINTER; } if (!str_to_cipher(cipher, &op->rnpctx.ealg)) { @@ -2451,7 +2667,7 @@ rnp_op_encrypt_set_aead(rnp_op_encrypt_t op, const char *alg) try { // checks - if (!op) { + if (!op || !alg) { return RNP_ERROR_NULL_POINTER; } if (!str_to_aead_alg(alg, &op->rnpctx.aalg)) { @@ -2844,7 +3060,8 @@ rnp_verify_dest_provider(pgp_parse_handler_t *handler, pgp_dest_t ** dst, bool * closedst, - const char * filename) + const char * filename, + uint32_t mtime) { rnp_op_verify_t op = (rnp_op_verify_t) handler->param; if (!op->output) { @@ -2853,6 +3070,7 @@ *dst = &(op->output->dst); *closedst = false; op->filename = filename ? strdup(filename) : NULL; + op->file_mtime = mtime; return true; } @@ -3068,6 +3286,9 @@ rnp_result_t rnp_op_verify_get_file_info(rnp_op_verify_t op, char **filename, uint32_t *mtime) try { + if (!op) { + return RNP_ERROR_NULL_POINTER; + } if (mtime) { *mtime = op->file_mtime; } @@ -3110,9 +3331,7 @@ if (!op->encrypted) { return "none"; } - const char *str = "unknown"; - ARRAY_LOOKUP_BY_ID(symm_alg_map, type, string, op->salg, str); - return str; + return id_str_pair::lookup(symm_alg_map, op->salg); } rnp_result_t @@ -3197,7 +3416,7 @@ if (!recipient || !alg) { return RNP_ERROR_NULL_POINTER; } - return get_map_value(pubkey_alg_map, ARRAY_SIZE(pubkey_alg_map), recipient->palg, alg); + return get_map_value(pubkey_alg_map, recipient->palg, alg); } FFI_GUARD @@ -3243,7 +3462,7 @@ if (!symenc || !cipher) { return RNP_ERROR_NULL_POINTER; } - return get_map_value(symm_alg_map, ARRAY_SIZE(symm_alg_map), symenc->alg, cipher); + return get_map_value(symm_alg_map, symenc->alg, cipher); } FFI_GUARD @@ -3253,7 +3472,7 @@ if (!symenc || !alg) { return RNP_ERROR_NULL_POINTER; } - return get_map_value(aead_alg_map, ARRAY_SIZE(aead_alg_map), symenc->aalg, alg); + return get_map_value(aead_alg_map, symenc->aalg, alg); } FFI_GUARD @@ -3263,7 +3482,7 @@ if (!symenc || !alg) { return RNP_ERROR_NULL_POINTER; } - return get_map_value(hash_alg_map, ARRAY_SIZE(hash_alg_map), symenc->halg, alg); + return get_map_value(hash_alg_map, symenc->halg, alg); } FFI_GUARD @@ -3273,7 +3492,7 @@ if (!symenc || !type) { return RNP_ERROR_NULL_POINTER; } - return get_map_value(s2k_type_map, ARRAY_SIZE(s2k_type_map), symenc->s2k_type, type); + return get_map_value(s2k_type_map, symenc->s2k_type, type); } FFI_GUARD @@ -3349,7 +3568,7 @@ if (!sig || !hash) { return RNP_ERROR_NULL_POINTER; } - return get_map_value(hash_alg_map, ARRAY_SIZE(hash_alg_map), sig->sig_pkt.halg, hash); + return get_map_value(hash_alg_map, sig->sig_pkt.halg, hash); } FFI_GUARD @@ -3406,7 +3625,8 @@ rnp_decrypt_dest_provider(pgp_parse_handler_t *handler, pgp_dest_t ** dst, bool * closedst, - const char * filename) + const char * filename, + uint32_t mtime) { *dst = &((rnp_output_t) handler->param)->dst; *closedst = false; @@ -3445,8 +3665,8 @@ const char * identifier) { // parse the identifier type - locator->type = PGP_KEY_SEARCH_UNKNOWN; - ARRAY_LOOKUP_BY_STRCASE(identifier_type_map, string, type, identifier_type, locator->type); + locator->type = static_cast( + id_str_pair::lookup(identifier_type_map, identifier_type, PGP_KEY_SEARCH_UNKNOWN)); if (locator->type == PGP_KEY_SEARCH_UNKNOWN) { FFI_LOG(ffi, "Invalid identifier type: %s", identifier_type); return RNP_ERROR_BAD_PARAMETERS; @@ -3503,8 +3723,7 @@ size_t identifier_size) { // find the identifier type string with the map - *identifier_type = NULL; - ARRAY_LOOKUP_BY_ID(identifier_type_map, type, string, locator->type, *identifier_type); + *identifier_type = id_str_pair::lookup(identifier_type_map, locator->type, NULL); if (!*identifier_type) { return false; } @@ -3546,13 +3765,21 @@ } static rnp_result_t -rnp_locate_key_int(rnp_ffi_t ffi, const pgp_key_search_t &locator, rnp_key_handle_t *handle) +rnp_locate_key_int(rnp_ffi_t ffi, + const pgp_key_search_t &locator, + rnp_key_handle_t * handle, + bool require_secret = false) { // search pubring pgp_key_t *pub = rnp_key_store_search(ffi->pubring, &locator, NULL); // search secring pgp_key_t *sec = rnp_key_store_search(ffi->secring, &locator, NULL); + if (require_secret && !sec) { + *handle = NULL; + return RNP_SUCCESS; + } + if (pub || sec) { *handle = (rnp_key_handle_t) malloc(sizeof(**handle)); if (!*handle) { @@ -3768,15 +3995,14 @@ } static rnp_result_t -rnp_key_get_revocation(rnp_ffi_t ffi, - pgp_key_t * key, - pgp_key_t * revoker, - const char * hash, - const char * code, - const char * reason, - pgp_signature_t **sig) +rnp_key_get_revocation(rnp_ffi_t ffi, + pgp_key_t * key, + pgp_key_t * revoker, + const char * hash, + const char * code, + const char * reason, + pgp_signature_t &sig) { - *sig = NULL; if (!hash) { hash = DEFAULT_HASH_ALG; } @@ -3803,19 +4029,18 @@ } } /* unlock the secret key if needed */ - bool locked = revoker->is_locked(); - if (locked && !revoker->unlock(ffi->pass_provider)) { + rnp::KeyLocker revlock(*revoker); + if (revoker->is_locked() && !revoker->unlock(ffi->pass_provider)) { FFI_LOG(ffi, "Failed to unlock secret key"); return RNP_ERROR_BAD_PASSWORD; } - *sig = transferable_key_revoke(key->pkt(), revoker->pkt(), halg, revinfo); - if (!*sig) { - FFI_LOG(ffi, "Failed to generate revocation signature"); - } - if (locked) { - revoker->lock(); + try { + revoker->gen_revocation(revinfo, halg, key->pkt(), sig, ffi->context); + } catch (const std::exception &e) { + FFI_LOG(ffi, "Failed to generate revocation signature: %s", e.what()); + return RNP_ERROR_BAD_STATE; } - return *sig ? RNP_SUCCESS : RNP_ERROR_BAD_STATE; + return RNP_SUCCESS; } rnp_result_t @@ -3843,18 +4068,17 @@ return RNP_ERROR_BAD_PARAMETERS; } - pgp_signature_t *sig = NULL; - rnp_result_t ret = - rnp_key_get_revocation(key->ffi, exkey, revoker, hash, code, reason, &sig); + pgp_signature_t sig; + rnp_result_t ret = + rnp_key_get_revocation(key->ffi, exkey, revoker, hash, code, reason, sig); if (ret) { return ret; } - sig->write(output->dst); + sig.write(output->dst); ret = output->dst.werr; dst_flush(&output->dst); output->keep = !ret; - delete sig; return ret; } FFI_GUARD @@ -3880,21 +4104,20 @@ return RNP_ERROR_BAD_PARAMETERS; } - pgp_signature_t *sig = NULL; - rnp_result_t ret = - rnp_key_get_revocation(key->ffi, exkey, revoker, hash, code, reason, &sig); + pgp_signature_t sig; + rnp_result_t ret = + rnp_key_get_revocation(key->ffi, exkey, revoker, hash, code, reason, sig); if (ret) { return ret; } pgp_sig_import_status_t pub_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY; pgp_sig_import_status_t sec_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY; if (key->pub) { - pub_status = rnp_key_store_import_key_signature(key->ffi->pubring, key->pub, sig); + pub_status = rnp_key_store_import_key_signature(key->ffi->pubring, key->pub, &sig); } if (key->sec) { - sec_status = rnp_key_store_import_key_signature(key->ffi->secring, key->sec, sig); + sec_status = rnp_key_store_import_key_signature(key->ffi->secring, key->sec, &sig); } - delete sig; if ((pub_status == PGP_SIG_IMPORT_STATUS_UNKNOWN) || (sec_status == PGP_SIG_IMPORT_STATUS_UNKNOWN)) { @@ -3905,6 +4128,45 @@ FFI_GUARD rnp_result_t +rnp_key_25519_bits_tweaked(rnp_key_handle_t key, bool *result) +try { + if (!key || !result) { + return RNP_ERROR_NULL_POINTER; + } + pgp_key_t *seckey = get_key_require_secret(key); + if (!seckey || seckey->is_locked() || (seckey->alg() != PGP_PKA_ECDH) || + (seckey->curve() != PGP_CURVE_25519)) { + return RNP_ERROR_BAD_PARAMETERS; + } + *result = x25519_bits_tweaked(seckey->material().ec); + return RNP_SUCCESS; +} +FFI_GUARD + +rnp_result_t +rnp_key_25519_bits_tweak(rnp_key_handle_t key) +try { + if (!key) { + return RNP_ERROR_NULL_POINTER; + } + pgp_key_t *seckey = get_key_require_secret(key); + if (!seckey || seckey->is_protected() || (seckey->alg() != PGP_PKA_ECDH) || + (seckey->curve() != PGP_CURVE_25519)) { + return RNP_ERROR_BAD_PARAMETERS; + } + if (!x25519_tweak_bits(seckey->pkt().material.ec)) { + FFI_LOG(key->ffi, "Failed to tweak 25519 key bits."); + return RNP_ERROR_BAD_STATE; + } + if (!seckey->write_sec_rawpkt(seckey->pkt(), "", key->ffi->rng())) { + FFI_LOG(key->ffi, "Failed to update rawpkt."); + return RNP_ERROR_BAD_STATE; + } + return RNP_SUCCESS; +} +FFI_GUARD + +rnp_result_t rnp_key_remove(rnp_key_handle_t key, uint32_t flags) try { if (!key || !key->ffi) { @@ -3977,6 +4239,7 @@ sig->ffi = ffi; sig->key = &key; sig->sig = &keysig; + sig->own_sig = false; uint32_t action = remove ? RNP_KEY_SIGNATURE_REMOVE : RNP_KEY_SIGNATURE_KEEP; sigcb(ffi, app_ctx, sig, &action); switch (action) { @@ -4014,7 +4277,7 @@ } /* validate signature if didn't */ if (signer && !sig.validated()) { - signer->validate_sig(key, sig); + signer->validate_sig(key, sig, ffi->context); } /* we cannot check for invalid/expired if sig was not validated */ if (!sig.validated()) { @@ -4146,7 +4409,7 @@ return false; } try { - if (!rnp_strcasecmp(key, "hashes")) { + if (rnp::str_case_eq(key, "hashes")) { int length = json_object_array_length(value); for (int i = 0; i < length; i++) { json_object *item = json_object_array_get_idx(value, i); @@ -4159,7 +4422,7 @@ } prefs.add_hash_alg(hash_alg); } - } else if (!rnp_strcasecmp(key, "ciphers")) { + } else if (rnp::str_case_eq(key, "ciphers")) { int length = json_object_array_length(value); for (int i = 0; i < length; i++) { json_object *item = json_object_array_get_idx(value, i); @@ -4172,7 +4435,7 @@ } prefs.add_symm_alg(symm_alg); } - } else if (!rnp_strcasecmp(key, "compression")) { + } else if (rnp::str_case_eq(key, "compression")) { int length = json_object_array_length(value); for (int i = 0; i < length; i++) { json_object *item = json_object_array_get_idx(value, i); @@ -4185,7 +4448,7 @@ } prefs.add_z_alg(z_alg); } - } else if (!rnp_strcasecmp(key, "key server")) { + } else if (rnp::str_case_eq(key, "key server")) { prefs.key_server = json_object_get_string(value); } } catch (const std::exception &e) { @@ -4221,11 +4484,11 @@ return false; } // TODO: make sure there are no duplicate keys in the JSON - if (!rnp_strcasecmp(key, "type")) { + if (rnp::str_case_eq(key, "type")) { if (!str_to_pubkey_alg(json_object_get_string(value), &crypto->key_alg)) { return false; } - } else if (!rnp_strcasecmp(key, "length")) { + } else if (rnp::str_case_eq(key, "length")) { int length = json_object_get_int(value); switch (crypto->key_alg) { case PGP_PKA_RSA: @@ -4240,14 +4503,14 @@ default: return false; } - } else if (!rnp_strcasecmp(key, "curve")) { + } else if (rnp::str_case_eq(key, "curve")) { if (!pk_alg_allows_custom_curve(crypto->key_alg)) { return false; } if (!curve_str_to_type(json_object_get_string(value), &crypto->ecc.curve)) { return false; } - } else if (!rnp_strcasecmp(key, "hash")) { + } else if (rnp::str_case_eq(key, "hash")) { if (!str_to_hash_alg(json_object_get_string(value), &crypto->hash_alg)) { return false; } @@ -4284,17 +4547,17 @@ return false; } // TODO: make sure there are no duplicate keys in the JSON - if (!rnp_strcasecmp(key, "cipher")) { + if (rnp::str_case_eq(key, "cipher")) { if (!str_to_cipher(json_object_get_string(value), &protection->symm_alg)) { return false; } - } else if (!rnp_strcasecmp(key, "mode")) { + } else if (rnp::str_case_eq(key, "mode")) { if (!str_to_cipher_mode(json_object_get_string(value), &protection->cipher_mode)) { return false; } - } else if (!rnp_strcasecmp(key, "iterations")) { + } else if (rnp::str_case_eq(key, "iterations")) { protection->iterations = json_object_get_int(value); - } else if (!rnp_strcasecmp(key, "hash")) { + } else if (rnp::str_case_eq(key, "hash")) { if (!str_to_hash_alg(json_object_get_string(value), &protection->hash_alg)) { return false; } @@ -4325,7 +4588,7 @@ if (!json_object_object_get_ex(jso, key, &value)) { continue; } - if (!rnp_strcasecmp(key, "userid")) { + if (rnp::str_case_eq(key, "userid")) { if (!json_object_is_type(value, json_type_string)) { return false; } @@ -4335,7 +4598,7 @@ return false; } memcpy(cert->userid, userid, userid_len + 1); - } else if (!rnp_strcasecmp(key, "usage")) { + } else if (rnp::str_case_eq(key, "usage")) { switch (json_object_get_type(value)) { case json_type_array: { int length = json_object_array_length(value); @@ -4363,12 +4626,12 @@ default: return false; } - } else if (!rnp_strcasecmp(key, "expiration")) { + } else if (rnp::str_case_eq(key, "expiration")) { if (!json_object_is_type(value, json_type_int)) { return false; } cert->key_expiration = json_object_get_int(value); - } else if (!rnp_strcasecmp(key, "preferences")) { + } else if (rnp::str_case_eq(key, "preferences")) { if (!json_object_is_type(value, json_type_object)) { return false; } @@ -4378,7 +4641,7 @@ if (json_object_object_length(value) != 0) { return false; } - } else if (!rnp_strcasecmp(key, "protection")) { + } else if (rnp::str_case_eq(key, "protection")) { if (!json_object_is_type(value, json_type_object)) { return false; } @@ -4411,7 +4674,7 @@ if (!json_object_object_get_ex(jso, key, &value)) { continue; } - if (!rnp_strcasecmp(key, "usage")) { + if (rnp::str_case_eq(key, "usage")) { switch (json_object_get_type(value)) { case json_type_array: { int length = json_object_array_length(value); @@ -4438,12 +4701,12 @@ default: return false; } - } else if (!rnp_strcasecmp(key, "expiration")) { + } else if (rnp::str_case_eq(key, "expiration")) { if (!json_object_is_type(value, json_type_int)) { return false; } binding->key_expiration = json_object_get_int(value); - } else if (!rnp_strcasecmp(key, "protection")) { + } else if (rnp::str_case_eq(key, "protection")) { if (!json_object_is_type(value, json_type_object)) { return false; } @@ -4551,9 +4814,9 @@ { json_object **dest = NULL; - if (rnp_strcasecmp(key, "primary") == 0) { + if (rnp::str_case_eq(key, "primary")) { dest = &jsoprimary; - } else if (rnp_strcasecmp(key, "sub") == 0) { + } else if (rnp::str_case_eq(key, "sub")) { dest = &jsosub; } else { // unrecognized key in the object @@ -4577,14 +4840,15 @@ ret = RNP_ERROR_BAD_PARAMETERS; goto done; } - if (!pgp_generate_keypair(&ffi->rng, - &keygen_desc.primary.keygen, - &keygen_desc.subkey.keygen, + keygen_desc.primary.keygen.crypto.ctx = &ffi->context; + keygen_desc.subkey.keygen.crypto.ctx = &ffi->context; + if (!pgp_generate_keypair(keygen_desc.primary.keygen, + keygen_desc.subkey.keygen, true, - &primary_sec, - &primary_pub, - &sub_sec, - &sub_pub, + primary_sec, + primary_pub, + sub_sec, + sub_pub, ffi->secring->format)) { goto done; } @@ -4604,13 +4868,14 @@ } /* add key/subkey protection */ if (keygen_desc.primary.protection.symm_alg && - !primary_sec.protect(keygen_desc.primary.protection, ffi->pass_provider)) { + !primary_sec.protect( + keygen_desc.primary.protection, ffi->pass_provider, ffi->rng())) { ret = RNP_ERROR_BAD_PARAMETERS; goto done; } if (keygen_desc.subkey.protection.symm_alg && - !sub_sec.protect(keygen_desc.subkey.protection, ffi->pass_provider)) { + !sub_sec.protect(keygen_desc.subkey.protection, ffi->pass_provider, ffi->rng())) { ret = RNP_ERROR_BAD_PARAMETERS; goto done; } @@ -4624,15 +4889,15 @@ goto done; } } else if (jsoprimary && !jsosub) { // generating primary only - keygen_desc.primary.keygen.crypto.rng = &ffi->rng; + keygen_desc.primary.keygen.crypto.ctx = &ffi->context; if (!parse_keygen_primary(jsoprimary, &keygen_desc)) { ret = RNP_ERROR_BAD_PARAMETERS; goto done; } - if (!pgp_generate_primary_key(&keygen_desc.primary.keygen, + if (!pgp_generate_primary_key(keygen_desc.primary.keygen, true, - &primary_sec, - &primary_pub, + primary_sec, + primary_pub, ffi->secring->format)) { goto done; } @@ -4648,7 +4913,8 @@ } /* encrypt secret key if specified */ if (keygen_desc.primary.protection.symm_alg && - !primary_sec.protect(keygen_desc.primary.protection, ffi->pass_provider)) { + !primary_sec.protect( + keygen_desc.primary.protection, ffi->pass_provider, ffi->rng())) { ret = RNP_ERROR_BAD_PARAMETERS; goto done; } @@ -4681,7 +4947,6 @@ ret = RNP_ERROR_OUT_OF_MEMORY; goto done; } - rnp_strlwr(identifier_type); json_object_object_del(jsosub, "primary"); pgp_key_search_t locator = {(pgp_key_search_type_t) 0}; @@ -4701,14 +4966,14 @@ ret = RNP_ERROR_BAD_PARAMETERS; goto done; } - keygen_desc.subkey.keygen.crypto.rng = &ffi->rng; - if (!pgp_generate_subkey(&keygen_desc.subkey.keygen, + keygen_desc.subkey.keygen.crypto.ctx = &ffi->context; + if (!pgp_generate_subkey(keygen_desc.subkey.keygen, true, - primary_sec, - primary_pub, - &sub_sec, - &sub_pub, - &ffi->pass_provider, + *primary_sec, + *primary_pub, + sub_sec, + sub_pub, + ffi->pass_provider, ffi->secring->format)) { goto done; } @@ -4724,7 +4989,7 @@ } /* encrypt subkey if specified */ if (keygen_desc.subkey.protection.symm_alg && - !sub_sec.protect(keygen_desc.subkey.protection, ffi->pass_provider)) { + !sub_sec.protect(keygen_desc.subkey.protection, ffi->pass_provider, ffi->rng())) { ret = RNP_ERROR_BAD_PARAMETERS; goto done; } @@ -4969,7 +5234,7 @@ (*op)->ffi = ffi; (*op)->primary = true; (*op)->crypto.key_alg = key_alg; - (*op)->crypto.rng = &ffi->rng; + (*op)->crypto.ctx = &ffi->context; (*op)->cert.key_flags = default_key_flags(key_alg, false); return RNP_SUCCESS; @@ -5013,7 +5278,7 @@ (*op)->ffi = ffi; (*op)->primary = false; (*op)->crypto.key_alg = key_alg; - (*op)->crypto.rng = &ffi->rng; + (*op)->crypto.ctx = &ffi->context; (*op)->binding.key_flags = default_key_flags(key_alg, true); (*op)->primary_sec = primary->sec; (*op)->primary_pub = primary->pub; @@ -5363,7 +5628,7 @@ keygen.cert = op->cert; op->cert.prefs = {}; /* generate call will free prefs */ - if (!pgp_generate_primary_key(&keygen, true, &sec, &pub, op->ffi->secring->format)) { + if (!pgp_generate_primary_key(keygen, true, sec, pub, op->ffi->secring->format)) { return RNP_ERROR_KEY_GENERATION; } } else { @@ -5371,13 +5636,13 @@ rnp_keygen_subkey_desc_t keygen = {}; keygen.crypto = op->crypto; keygen.binding = op->binding; - if (!pgp_generate_subkey(&keygen, + if (!pgp_generate_subkey(keygen, true, - op->primary_sec, - op->primary_pub, - &sec, - &pub, - &op->ffi->pass_provider, + *op->primary_sec, + *op->primary_pub, + sec, + pub, + op->ffi->pass_provider, op->ffi->secring->format)) { return RNP_ERROR_KEY_GENERATION; } @@ -5396,7 +5661,7 @@ } else if (op->request_password) { prov = {.callback = rnp_password_cb_bounce, .userdata = op->ffi}; } - if (prov.callback && !sec.protect(op->protection, prov)) { + if (prov.callback && !sec.protect(op->protection, prov, op->ffi->rng())) { FFI_LOG(op->ffi, "failed to encrypt the key"); ret = RNP_ERROR_BAD_PARAMETERS; goto done; @@ -5551,67 +5816,47 @@ uint8_t key_flags, bool primary) try { - rnp_result_t ret = RNP_ERROR_GENERIC; - rnp_selfsig_cert_info_t info = {}; - pgp_hash_alg_t hash_alg = PGP_HASH_UNKNOWN; - pgp_key_t * public_key = NULL; - pgp_key_t * secret_key = NULL; - pgp_key_pkt_t * seckey = NULL; - pgp_key_pkt_t * decrypted_seckey = NULL; - if (!handle || !uid) { return RNP_ERROR_NULL_POINTER; } - + /* setup parameters */ if (!hash) { hash = DEFAULT_HASH_ALG; } - + pgp_hash_alg_t hash_alg = PGP_HASH_UNKNOWN; if (!str_to_hash_alg(hash, &hash_alg)) { FFI_LOG(handle->ffi, "Invalid hash: %s", hash); return RNP_ERROR_BAD_PARAMETERS; } - size_t uid_len = strlen(uid); + rnp_selfsig_cert_info_t info = {}; + size_t uid_len = strlen(uid); if (uid_len >= sizeof(info.userid)) { FFI_LOG(handle->ffi, "UserID too long"); return RNP_ERROR_BAD_PARAMETERS; } memcpy(info.userid, uid, uid_len + 1); - info.key_flags = key_flags; info.key_expiration = expiration; info.primary = primary; - secret_key = get_key_require_secret(handle); + /* obtain and unlok secret key */ + pgp_key_t *secret_key = get_key_require_secret(handle); if (!secret_key) { return RNP_ERROR_NO_SUITABLE_KEY; } - public_key = get_key_prefer_public(handle); + pgp_key_t *public_key = get_key_prefer_public(handle); if (!public_key && secret_key->format == PGP_KEY_STORE_G10) { return RNP_ERROR_NO_SUITABLE_KEY; } - seckey = &secret_key->pkt(); - if (!seckey->material.secret) { - pgp_password_ctx_t ctx = {.op = PGP_OP_ADD_USERID, .key = secret_key}; - decrypted_seckey = pgp_decrypt_seckey(secret_key, &handle->ffi->pass_provider, &ctx); - if (!decrypted_seckey) { - return RNP_ERROR_BAD_PASSWORD; - } - seckey = decrypted_seckey; - } - if (public_key && !pgp_key_add_userid_certified(public_key, seckey, hash_alg, &info)) { - goto done; - } - if ((secret_key && secret_key->format != PGP_KEY_STORE_G10) && - !pgp_key_add_userid_certified(secret_key, seckey, hash_alg, &info)) { - goto done; + rnp::KeyLocker seclock(*secret_key); + if (secret_key->is_locked() && + !secret_key->unlock(handle->ffi->pass_provider, PGP_OP_ADD_USERID)) { + return RNP_ERROR_BAD_PASSWORD; } - - ret = RNP_SUCCESS; -done: - delete decrypted_seckey; - return ret; + /* add and certify userid */ + secret_key->add_uid_cert(info, hash_alg, handle->ffi->context, public_key); + return RNP_SUCCESS; } FFI_GUARD @@ -5882,8 +6127,7 @@ if (!handle->sig) { return RNP_ERROR_BAD_PARAMETERS; } - const char *sigtype = "unknown"; - ARRAY_LOOKUP_BY_ID(sig_type_map, type, string, handle->sig->sig.type(), sigtype); + auto sigtype = id_str_pair::lookup(sig_type_map, handle->sig->sig.type()); return ret_str_value(sigtype, type); } FFI_GUARD @@ -5897,8 +6141,7 @@ if (!handle->sig) { return RNP_ERROR_BAD_PARAMETERS; } - return get_map_value( - pubkey_alg_map, ARRAY_SIZE(pubkey_alg_map), handle->sig->sig.palg, alg); + return get_map_value(pubkey_alg_map, handle->sig->sig.palg, alg); } FFI_GUARD @@ -5911,7 +6154,7 @@ if (!handle->sig) { return RNP_ERROR_BAD_PARAMETERS; } - return get_map_value(hash_alg_map, ARRAY_SIZE(hash_alg_map), handle->sig->sig.halg, alg); + return get_map_value(hash_alg_map, handle->sig->sig.halg, alg); } FFI_GUARD @@ -5930,6 +6173,20 @@ FFI_GUARD rnp_result_t +rnp_signature_get_expiration(rnp_signature_handle_t handle, uint32_t *expires) +try { + if (!handle || !expires) { + return RNP_ERROR_NULL_POINTER; + } + if (!handle->sig) { + return RNP_ERROR_BAD_PARAMETERS; + } + *expires = handle->sig->sig.expiration(); + return RNP_SUCCESS; +} +FFI_GUARD + +rnp_result_t rnp_signature_get_keyid(rnp_signature_handle_t handle, char **result) try { if (!handle || !result) { @@ -5980,7 +6237,7 @@ if (!signer) { return RNP_ERROR_KEY_NOT_FOUND; } - signer->validate_sig(*sig->key, *sig->sig); + signer->validate_sig(*sig->key, *sig->sig, sig->ffi->context); } if (!sig->sig->validity.validated) { @@ -6207,33 +6464,20 @@ *default_key = NULL; return RNP_ERROR_NO_SUITABLE_KEY; } + pgp_key_search_t search = {(pgp_key_search_type_t) 0}; search.type = PGP_KEY_SEARCH_FINGERPRINT; search.by.fingerprint = defkey->fp(); - // search pubring - pgp_key_t *pub = rnp_key_store_search(primary_key->ffi->pubring, &search, NULL); - // search secring - pgp_key_t *sec = rnp_key_store_search(primary_key->ffi->secring, &search, NULL); + bool require_secret = keyflag != PGP_KF_ENCRYPT; + rnp_result_t ret = + rnp_locate_key_int(primary_key->ffi, search, default_key, require_secret); - if (!sec && keyflag != PGP_KF_ENCRYPT) { + if (!*default_key && !ret) { return RNP_ERROR_NO_SUITABLE_KEY; } - if (pub || sec) { - *default_key = (rnp_key_handle_t) malloc(sizeof(**default_key)); - if (!*default_key) { - return RNP_ERROR_OUT_OF_MEMORY; - } - (*default_key)->ffi = primary_key->ffi; - (*default_key)->pub = pub; - (*default_key)->sec = sec; - (*default_key)->locator = search; - } else { - *default_key = NULL; - return RNP_ERROR_NO_SUITABLE_KEY; - } - return RNP_SUCCESS; + return ret; } FFI_GUARD @@ -6244,7 +6488,7 @@ return RNP_ERROR_NULL_POINTER; } pgp_key_t *key = get_key_prefer_public(handle); - return get_map_value(pubkey_alg_map, ARRAY_SIZE(pubkey_alg_map), key->alg(), alg); + return get_map_value(pubkey_alg_map, key->alg(), alg); } FFI_GUARD @@ -6562,7 +6806,8 @@ } if (pkey->is_primary()) { - if (!pgp_key_set_expiration(pkey, skey, expiry, key->ffi->pass_provider)) { + if (!pgp_key_set_expiration( + pkey, skey, expiry, key->ffi->pass_provider, key->ffi->context)) { return RNP_ERROR_GENERIC; } pkey->revalidate(*key->ffi->pubring); @@ -6586,7 +6831,8 @@ FFI_LOG(key->ffi, "Primary secret key not found."); return RNP_ERROR_KEY_NOT_FOUND; } - if (!pgp_subkey_set_expiration(pkey, prim_sec, skey, expiry, key->ffi->pass_provider)) { + if (!pgp_subkey_set_expiration( + pkey, prim_sec, skey, expiry, key->ffi->pass_provider, key->ffi->context)) { return RNP_ERROR_GENERIC; } prim_sec->revalidate(*key->ffi->secring); @@ -6705,10 +6951,7 @@ return ret_str_value("Unknown", mode); } - return get_map_value(cipher_mode_map, - ARRAY_SIZE(cipher_mode_map), - key->sec->pkt().sec_protection.cipher_mode, - mode); + return get_map_value(cipher_mode_map, key->sec->pkt().sec_protection.cipher_mode, mode); } FFI_GUARD @@ -6732,8 +6975,7 @@ return RNP_ERROR_BAD_PARAMETERS; } - return get_map_value( - symm_alg_map, ARRAY_SIZE(symm_alg_map), key->sec->pkt().sec_protection.symm_alg, cipher); + return get_map_value(symm_alg_map, key->sec->pkt().sec_protection.symm_alg, cipher); } FFI_GUARD @@ -6750,10 +6992,7 @@ return RNP_ERROR_BAD_PARAMETERS; } - return get_map_value(hash_alg_map, - ARRAY_SIZE(hash_alg_map), - key->sec->pkt().sec_protection.s2k.hash_alg, - hash); + return get_map_value(hash_alg_map, key->sec->pkt().sec_protection.s2k.hash_alg, hash); } FFI_GUARD @@ -6823,8 +7062,9 @@ } bool ok = false; if (password) { - pgp_password_provider_t prov = {.callback = rnp_password_provider_string, - .userdata = RNP_CONST_TO_VOID_PTR(password)}; + pgp_password_provider_t prov = { + .callback = rnp_password_provider_string, + .userdata = reinterpret_cast(const_cast(password))}; ok = key->unlock(prov); } else { ok = key->unlock(handle->ffi->pass_provider); @@ -6890,12 +7130,13 @@ const std::string pass = password; if (key->encrypted()) { pgp_password_ctx_t ctx = {.op = PGP_OP_PROTECT, .key = key}; - decrypted_key = pgp_decrypt_seckey(key, &handle->ffi->pass_provider, &ctx); + decrypted_key = pgp_decrypt_seckey(*key, handle->ffi->pass_provider, ctx); if (!decrypted_key) { return RNP_ERROR_GENERIC; } } - bool res = key->protect(decrypted_key ? *decrypted_key : key->pkt(), protection, pass); + bool res = key->protect( + decrypted_key ? *decrypted_key : key->pkt(), protection, pass, handle->ffi->rng()); delete decrypted_key; return res ? RNP_SUCCESS : RNP_ERROR_GENERIC; } @@ -6916,11 +7157,12 @@ } bool ok = false; if (password) { - pgp_password_provider_t prov = {.callback = rnp_password_provider_string, - .userdata = RNP_CONST_TO_VOID_PTR(password)}; - ok = key->unprotect(prov); + pgp_password_provider_t prov = { + .callback = rnp_password_provider_string, + .userdata = reinterpret_cast(const_cast(password))}; + ok = key->unprotect(prov, handle->ffi->rng()); } else { - ok = key->unprotect(handle->ffi->pass_provider); + ok = key->unprotect(handle->ffi->pass_provider, handle->ffi->rng()); } if (!ok) { // likely a bad password @@ -7069,13 +7311,12 @@ return false; } for (size_t i = 0; i < ARRAY_SIZE(key_usage_map); i++) { - if (key_usage_map[i].mask & key_flags) { - json_object *jsostr = json_object_new_string(key_usage_map[i].string); - if (!jsostr) { + if (key_usage_map[i].id & key_flags) { + json_object *jsostr = json_object_new_string(key_usage_map[i].str); + if (!jsostr || json_object_array_add(jsoarr, jsostr)) { json_object_put(jsoarr); return false; } - json_object_array_add(jsoarr, jsostr); } } if (json_object_array_length(jsoarr)) { @@ -7094,13 +7335,12 @@ return false; } for (size_t i = 0; i < ARRAY_SIZE(key_flags_map); i++) { - if (key_flags_map[i].mask & key_flags) { - json_object *jsostr = json_object_new_string(key_flags_map[i].string); - if (!jsostr) { + if (key_flags_map[i].id & key_flags) { + json_object *jsostr = json_object_new_string(key_flags_map[i].str); + if (!jsostr || json_object_array_add(jsoarr, jsostr)) { json_object_put(jsoarr); return false; } - json_object_array_add(jsoarr, jsostr); } } if (json_object_array_length(jsoarr)) { @@ -7243,8 +7483,7 @@ } json_object_object_add(jso, "ciphers", jsoarr); for (auto alg : prefs.symm_algs) { - const char *name = "Unknown"; - ARRAY_LOOKUP_BY_ID(symm_alg_map, type, string, alg, name); + const char * name = id_str_pair::lookup(symm_alg_map, alg, "Unknown"); json_object *jsoname = json_object_new_string(name); if (!jsoname || json_object_array_add(jsoarr, jsoname)) { return false; @@ -7258,8 +7497,7 @@ } json_object_object_add(jso, "hashes", jsoarr); for (auto alg : prefs.hash_algs) { - const char *name = "Unknown"; - ARRAY_LOOKUP_BY_ID(hash_alg_map, type, string, alg, name); + const char * name = id_str_pair::lookup(hash_alg_map, alg, "Unknown"); json_object *jsoname = json_object_new_string(name); if (!jsoname || json_object_array_add(jsoarr, jsoname)) { return false; @@ -7273,8 +7511,7 @@ } json_object_object_add(jso, "compression", jsoarr); for (auto alg : prefs.z_algs) { - const char *name = "Unknown"; - ARRAY_LOOKUP_BY_ID(compress_alg_map, type, string, alg, name); + const char * name = id_str_pair::lookup(compress_alg_map, alg, "Unknown"); json_object *jsoname = json_object_new_string(name); if (!jsoname || json_object_array_add(jsoarr, jsoname)) { return false; @@ -7288,8 +7525,7 @@ } json_object_object_add(jso, "key server preferences", jsoarr); for (auto flag : prefs.ks_prefs) { - const char *name = "Unknown"; - ARRAY_LOOKUP_BY_ID(key_server_prefs_map, type, string, flag, name); + const char * name = id_str_pair::lookup(key_server_prefs_map, flag, "Unknown"); json_object *jsoname = json_object_new_string(name); if (!jsoname || json_object_array_add(jsoarr, jsoname)) { return false; @@ -7362,20 +7598,17 @@ } json_object_object_add(jso, "version", jsoversion); // signature type - const char *type = "unknown"; - ARRAY_LOOKUP_BY_ID(sig_type_map, type, string, sig->type(), type); + auto type = id_str_pair::lookup(sig_type_map, sig->type()); if (!add_json_string_field(jso, "type", type)) { return RNP_ERROR_OUT_OF_MEMORY; } // signer key type - const char *key_type = "unknown"; - ARRAY_LOOKUP_BY_ID(pubkey_alg_map, type, string, sig->palg, key_type); + const char *key_type = id_str_pair::lookup(pubkey_alg_map, sig->palg); if (!add_json_string_field(jso, "key type", key_type)) { return RNP_ERROR_OUT_OF_MEMORY; } // hash - const char *hash = "unknown"; - ARRAY_LOOKUP_BY_ID(hash_alg_map, type, string, sig->halg, hash); + const char *hash = id_str_pair::lookup(hash_alg_map, sig->halg); if (!add_json_string_field(jso, "hash", hash)) { return RNP_ERROR_OUT_OF_MEMORY; } @@ -7430,14 +7663,10 @@ static rnp_result_t key_to_json(json_object *jso, rnp_key_handle_t handle, uint32_t flags) { - bool have_sec = handle->sec != NULL; - bool have_pub = handle->pub != NULL; - pgp_key_t * key = get_key_prefer_public(handle); - const char * str = NULL; - const pgp_key_material_t &material = key->material(); + pgp_key_t *key = get_key_prefer_public(handle); // type - ARRAY_LOOKUP_BY_ID(pubkey_alg_map, type, string, key->alg(), str); + const char *str = id_str_pair::lookup(pubkey_alg_map, key->alg(), NULL); if (!str) { return RNP_ERROR_BAD_PARAMETERS; } @@ -7451,13 +7680,13 @@ // curve / alg-specific items switch (key->alg()) { case PGP_PKA_ECDH: { - const char *hash_name = NULL; - ARRAY_LOOKUP_BY_ID(hash_alg_map, type, string, material.ec.kdf_hash_alg, hash_name); + const char *hash_name = + id_str_pair::lookup(hash_alg_map, key->material().ec.kdf_hash_alg, NULL); if (!hash_name) { return RNP_ERROR_BAD_PARAMETERS; } - const char *cipher_name = NULL; - ARRAY_LOOKUP_BY_ID(symm_alg_map, type, string, material.ec.key_wrap_alg, cipher_name); + const char *cipher_name = + id_str_pair::lookup(symm_alg_map, key->material().ec.key_wrap_alg, NULL); if (!cipher_name) { return RNP_ERROR_BAD_PARAMETERS; } @@ -7471,12 +7700,13 @@ return RNP_ERROR_OUT_OF_MEMORY; } json_object_object_add(jso, "key wrap cipher", jsocipher); - } // fall through + } + [[fallthrough]]; case PGP_PKA_ECDSA: case PGP_PKA_EDDSA: case PGP_PKA_SM2: { const char *curve_name = NULL; - if (!curve_type_to_str(material.ec.curve, &curve_name)) { + if (!curve_type_to_str(key->material().ec.curve, &curve_name)) { return RNP_ERROR_BAD_PARAMETERS; } json_object *jsocurve = json_object_new_string(curve_name); @@ -7576,6 +7806,8 @@ if (!jsopublic) { return RNP_ERROR_OUT_OF_MEMORY; } + bool have_sec = handle->sec != NULL; + bool have_pub = handle->pub != NULL; json_object_object_add(jso, "public key", jsopublic); json_object_object_add( jsopublic, "present", json_object_new_boolean(have_pub ? true : false)); @@ -7845,10 +8077,6 @@ } // we've gone through both rings it->store = NULL; - if (it->keyp) { - delete it->keyp; - it->keyp = NULL; - } return false; } @@ -7888,7 +8116,7 @@ it->store = NULL; return false; } - it->keyp = new std::list::iterator(it->store->keys.begin()); + *it->keyp = it->store->keys.begin(); it->uididx = 0; return true; } @@ -7975,9 +8203,11 @@ return RNP_ERROR_OUT_OF_MEMORY; } obj->ffi = ffi; + obj->keyp = new std::list::iterator(); + obj->uididx = 0; // parse identifier type - obj->type = PGP_KEY_SEARCH_UNKNOWN; - ARRAY_LOOKUP_BY_STRCASE(identifier_type_map, string, type, identifier_type, obj->type); + obj->type = static_cast( + id_str_pair::lookup(identifier_type_map, identifier_type, PGP_KEY_SEARCH_UNKNOWN)); if (obj->type == PGP_KEY_SEARCH_UNKNOWN) { ret = RNP_ERROR_BAD_PARAMETERS; goto done; @@ -8081,9 +8311,8 @@ } else { msgtype = rnp_armor_guess_type(&input->src); } - const char *msg = "unknown"; - ARRAY_LOOKUP_BY_ID(armor_type_map, type, string, msgtype, msg); - size_t len = strlen(msg); + const char *msg = id_str_pair::lookup(armor_type_map, msgtype); + size_t len = strlen(msg); *contents = (char *) calloc(1, len + 1); if (!*contents) { return RNP_ERROR_OUT_OF_MEMORY; @@ -8101,8 +8330,9 @@ return RNP_ERROR_NULL_POINTER; } if (type) { - ARRAY_LOOKUP_BY_STRCASE(armor_type_map, string, type, type, msgtype); - if (!msgtype) { + msgtype = static_cast( + id_str_pair::lookup(armor_type_map, type, PGP_ARMORED_UNKNOWN)); + if (msgtype == PGP_ARMORED_UNKNOWN) { RNP_LOG("Unsupported armor type: %s", type); return RNP_ERROR_BAD_PARAMETERS; } @@ -8152,3 +8382,15 @@ return armored_dst_set_line_length(&output->dst, llen); } FFI_GUARD + +const char * +rnp_backend_string() +{ + return rnp::backend_string(); +} + +const char * +rnp_backend_version() +{ + return rnp::backend_version(); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/sec_profile.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/sec_profile.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/sec_profile.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/sec_profile.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2021 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sec_profile.hpp" +#include "types.h" +#include + +namespace rnp { +bool +SecurityRule::operator==(const SecurityRule &src) const +{ + return (type == src.type) && (feature == src.feature) && (from == src.from) && + (level == src.level) && (override == src.override); +} + +bool +SecurityRule::operator!=(const SecurityRule &src) const +{ + return !(*this == src); +} + +size_t +SecurityProfile::size() const noexcept +{ + return rules_.size(); +} + +SecurityRule & +SecurityProfile::add_rule(const SecurityRule &rule) +{ + rules_.push_back(rule); + return rules_.back(); +} + +SecurityRule & +SecurityProfile::add_rule(SecurityRule &&rule) +{ + rules_.emplace_back(rule); + return rules_.back(); +} + +bool +SecurityProfile::del_rule(const SecurityRule &rule) +{ + size_t old_size = rules_.size(); + rules_.erase(std::remove_if(rules_.begin(), + rules_.end(), + [rule](const SecurityRule &item) { return item == rule; }), + rules_.end()); + return old_size != rules_.size(); +} + +void +SecurityProfile::clear_rules(FeatureType type, int feature) +{ + rules_.erase(std::remove_if(rules_.begin(), + rules_.end(), + [type, feature](const SecurityRule &item) { + return (item.type == type) && (item.feature == feature); + }), + rules_.end()); +} + +void +SecurityProfile::clear_rules(FeatureType type) +{ + rules_.erase( + std::remove_if(rules_.begin(), + rules_.end(), + [type](const SecurityRule &item) { return item.type == type; }), + rules_.end()); +} + +void +SecurityProfile::clear_rules() +{ + rules_.clear(); +} + +bool +SecurityProfile::has_rule(FeatureType type, int value, uint64_t time) const noexcept +{ + for (auto &rule : rules_) { + if ((rule.type == type) && (rule.feature == value) && (rule.from <= time)) { + return true; + } + } + return false; +} + +const SecurityRule & +SecurityProfile::get_rule(FeatureType type, int value, uint64_t time) const +{ + const SecurityRule *res = nullptr; + for (auto &rule : rules_) { + if ((rule.type != type) || (rule.feature != value) || (rule.from > time)) { + continue; + } + if (rule.override) { + return rule; + } + if (!res || (res->from < rule.from)) { + res = &rule; + } + } + if (!res) { + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + return *res; +} + +SecurityLevel +SecurityProfile::hash_level(pgp_hash_alg_t hash, uint64_t time) const noexcept +{ + if (has_rule(FeatureType::Hash, hash, time)) { + return get_rule(FeatureType::Hash, hash, time).level; + } + return def_level(); +} + +SecurityLevel +SecurityProfile::def_level() const +{ + return SecurityLevel::Default; +}; + +SecurityContext::SecurityContext() : rng(RNG::Type::DRBG) +{ + /* Mark SHA-1 insecure since 2019-01-19, as GnuPG does */ + profile.add_rule( + SecurityRule(FeatureType::Hash, PGP_HASH_SHA1, SecurityLevel::Insecure, 1547856000)); + /* Mark MD5 insecure since 2012-01-01 */ + profile.add_rule( + SecurityRule(FeatureType::Hash, PGP_HASH_MD5, SecurityLevel::Insecure, 1325376000)); +} + +} // namespace rnp \ No newline at end of file diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/sec_profile.hpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/sec_profile.hpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/sec_profile.hpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/sec_profile.hpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef RNP_SEC_PROFILE_H_ +#define RNP_SEC_PROFILE_H_ + +#include +#include +#include "repgp/repgp_def.h" +#include "crypto/rng.h" + +namespace rnp { + +enum class FeatureType { Hash, Cipher, PublicKey }; +enum class SecurityLevel { Disabled, Insecure, Default }; + +struct SecurityRule { + FeatureType type; + int feature; + SecurityLevel level; + uint64_t from; + bool override; + + SecurityRule(FeatureType ftype, int fval, SecurityLevel flevel, uint64_t ffrom = 0) + : type(ftype), feature(fval), level(flevel), from(ffrom), override(false){}; + + bool operator==(const SecurityRule &src) const; + bool operator!=(const SecurityRule &src) const; +}; + +class SecurityProfile { + private: + std::vector rules_; + + public: + size_t size() const noexcept; + SecurityRule &add_rule(const SecurityRule &rule); + SecurityRule &add_rule(SecurityRule &&rule); + bool del_rule(const SecurityRule &rule); + void clear_rules(FeatureType type, int feature); + void clear_rules(FeatureType type); + void clear_rules(); + + bool has_rule(FeatureType type, int value, uint64_t time) const noexcept; + const SecurityRule &get_rule(FeatureType type, int value, uint64_t time) const; + SecurityLevel hash_level(pgp_hash_alg_t hash, uint64_t time) const noexcept; + SecurityLevel def_level() const; +}; + +class SecurityContext { + public: + SecurityProfile profile; + RNG rng; + + SecurityContext(); +}; +} // namespace rnp + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/types.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/types.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/types.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/types.h 2022-04-15 07:49:22.000000000 +0000 @@ -60,6 +60,7 @@ #include #include "crypto/common.h" +#include "sec_profile.hpp" /* SHA1 Hash Size */ #define PGP_SHA1_HASH_SIZE 20 @@ -73,17 +74,28 @@ /* Maximum supported password length */ #define MAX_PASSWORD_LENGTH 256 -/** pgp_map_t - */ -typedef struct { - int type; - const char *string; -} pgp_map_t; - -typedef struct { - uint8_t mask; - const char *string; -} pgp_bit_map_t; +class id_str_pair { + public: + int id; + const char *str; + + /** + * @brief Lookup constant pair array for the specified id or string value. + * Note: array must be finished with NULL string to stop the lookup. + * + * @param pair pointer to the const array with pairs. + * @param id identifier to search for + * @param notfound value to return if identifier is not found. + * @return string, representing the identifier. + */ + static const char *lookup(const id_str_pair pair[], + int id, + const char * notfound = "unknown"); + static int lookup(const id_str_pair pair[], const char *str, int notfound = 0); + static int lookup(const id_str_pair pair[], + const std::vector &bytes, + int notfound = 0); +}; /** pgp_fingerprint_t */ typedef struct pgp_fingerprint_t { @@ -147,12 +159,24 @@ }; } // namespace rnp +/* validity information for the signature/key/userid */ +typedef struct pgp_validity_t { + bool validated{}; /* item was validated */ + bool valid{}; /* item is valid by signature/key checks and calculations. + Still may be revoked or expired. */ + bool expired{}; /* item is expired */ + + void mark_valid(); + void reset(); +} pgp_validity_t; + /** * Type to keep public/secret key mpis without any openpgp-dependent data. */ typedef struct pgp_key_material_t { - pgp_pubkey_alg_t alg; /* algorithm of the key */ - bool secret; /* secret part of the key material is populated */ + pgp_pubkey_alg_t alg; /* algorithm of the key */ + bool secret; /* secret part of the key material is populated */ + pgp_validity_t validity; /* key material validation status */ union { pgp_rsa_key_t rsa; @@ -163,6 +187,8 @@ size_t bits() const; size_t qbits() const; + void validate(rnp::SecurityContext &ctx, bool reset = true); + bool valid() const; } pgp_key_material_t; /** @@ -251,11 +277,12 @@ } revocation_key; /* 5.2.3.15. Revocation Key */ uint8_t *issuer; /* 5.2.3.5. Issuer */ struct { - uint8_t flags[4]; - unsigned nlen; - unsigned vlen; - const char *name; - const char *value; + uint8_t flags[4]; + unsigned nlen; + unsigned vlen; + bool human; + const uint8_t *name; + const uint8_t *value; } notation; /* 5.2.3.16. Notation Data */ struct { bool no_modify; @@ -390,13 +417,17 @@ }; /* structure used to hold context of key generation */ +namespace rnp { +class SecurityContext; +} + typedef struct rnp_keygen_crypto_params_t { // Asymmteric algorithm that user requesed key for pgp_pubkey_alg_t key_alg; // Hash to be used for key signature pgp_hash_alg_t hash_alg; - // Pointer to initialized RNG engine - rng_t *rng; + // Pointer to security context + rnp::SecurityContext *ctx; union { struct rnp_keygen_ecc_params_t ecc; struct rnp_keygen_rsa_params_t rsa; @@ -411,6 +442,12 @@ uint32_t key_expiration{}; /* key expiration time (sec), 0 = no expiration */ pgp_user_prefs_t prefs{}; /* user preferences, optional */ bool primary : 1; /* mark this as the primary user id */ + + /** + * @brief Populate uid and sig packet with data stored in this struct. + * At some point we should get rid of it. + */ + void populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig); } rnp_selfsig_cert_info_t; typedef struct rnp_selfsig_binding_info_t { diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/utils.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/utils.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/utils.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/utils.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "types.h" +#include "str-utils.h" + +const char * +id_str_pair::lookup(const id_str_pair pair[], int id, const char *notfound) +{ + while (pair && pair->str) { + if (pair->id == id) { + return pair->str; + } + pair++; + } + return notfound; +} + +int +id_str_pair::lookup(const id_str_pair pair[], const char *str, int notfound) +{ + while (pair && pair->str) { + if (rnp::str_case_eq(str, pair->str)) { + return pair->id; + } + pair++; + } + return notfound; +} + +int +id_str_pair::lookup(const id_str_pair pair[], const std::vector &bytes, int notfound) +{ + while (pair && pair->str) { + if ((strlen(pair->str) == bytes.size()) && + !memcmp(pair->str, bytes.data(), bytes.size())) { + return pair->id; + } + pair++; + } + return notfound; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/utils.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/utils.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/utils.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/utils.h 2022-04-15 07:49:21.000000000 +0000 @@ -27,32 +27,12 @@ #define RNP_UTILS_H_ #include -#include "types.h" #include #include "logging.h" -#define RNP_DLOG(...) \ - if (rnp_get_debug(__FILE__)) { \ - RNP_LOG_FD(stderr, __VA_ARGS__); \ - } - -#define RNP_DHEX(msg, mem, len) \ - if (rnp_get_debug(__FILE__)) { \ - hexdump(stderr, msg, mem, len); \ - } - /* number of elements in an array */ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) -#define CHECK(exp, val, err) \ - do { \ - if ((exp) != (val)) { \ - RNP_LOG("ERROR: (" #exp ")!=(" #val ")"); \ - ret = (err); \ - goto end; \ - } \ - } while (false) - /* * @params * array: array of the structures to lookup @@ -71,44 +51,6 @@ } \ } while (0) -/* - * @params - * array: array of the structures to lookup - * str_field name of the field to compare against - * ret_field filed to return - * lookup_value lookup value - * ret return value - */ -#define ARRAY_LOOKUP_BY_STRCASE(array, str_field, ret_field, lookup_value, ret) \ - do { \ - for (size_t i__ = 0; i__ < ARRAY_SIZE(array); i__++) { \ - if (!rnp_strcasecmp((array)[i__].str_field, (lookup_value))) { \ - (ret) = static_cast(((array)[i__].ret_field)); \ - break; \ - } \ - } \ - } while (0) - -#ifndef RNP_CONST_TO_VOID_PTR -#define RNP_CONST_TO_VOID_PTR(a) (reinterpret_cast(const_cast(a))) -#endif - -int rnp_strcasecmp(const char *, const char *); - -char *rnp_strhexdump_upper(char *dest, const uint8_t *src, size_t length, const char *sep); - -char *rnp_strlwr(char *s); - -/* debugging helpers*/ -void hexdump(FILE *, const char *, const uint8_t *, size_t); - -const char *pgp_str_from_map(int, pgp_map_t *); - -/* debugging, reflection and information */ -bool rnp_set_debug(const char *); -bool rnp_get_debug(const char *); -void rnp_clear_debug(); - /* Portable way to convert bits to bytes */ #define BITS_TO_BYTES(b) (((b) + (CHAR_BIT - 1)) / CHAR_BIT) @@ -146,10 +88,6 @@ x[7] = (uint8_t)(y >> 0) & 0xff; } -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif - inline char * getenv_logname(void) { diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/version.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/version.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/lib/version.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/lib/version.h 2022-04-15 07:49:22.000000000 +0000 @@ -24,13 +24,13 @@ */ #define RNP_VERSION_MAJOR 0 -#define RNP_VERSION_MINOR 15 -#define RNP_VERSION_PATCH 2 +#define RNP_VERSION_MINOR 16 +#define RNP_VERSION_PATCH 0 -#define RNP_VERSION_STRING "0.15.2" -#define RNP_VERSION_STRING_FULL "0.15.2+git20210806.dd923a4e.MZLA" +#define RNP_VERSION_STRING "0.16" +#define RNP_VERSION_STRING_FULL "0.16+git20220124.f06439f7.MZLA" -#define RNP_VERSION_COMMIT_TIMESTAMP 1628243430 +#define RNP_VERSION_COMMIT_TIMESTAMP 1643016550 // using a 32-bit version with 10 bits per component #define RNP_VERSION_COMPONENT_MASK 0x3ff diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/g10_sexp.hpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/g10_sexp.hpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/g10_sexp.hpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/g10_sexp.hpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE RIBOSE, INC. AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RNP_G10_SEXP_HPP +#define RNP_G10_SEXP_HPP + +#define SXP_MAX_DEPTH 30 + +class s_exp_element_t { + protected: + bool is_block_; + + public: + s_exp_element_t(bool block) : is_block_(block){}; + virtual ~s_exp_element_t() = default; + virtual bool + write(pgp_dest_t &dst) const noexcept + { + return false; + }; + + bool + is_block() + { + return is_block_; + } +}; + +class s_exp_block_t : public s_exp_element_t { + protected: + std::vector bytes_; + + public: + s_exp_block_t(const uint8_t *bt = NULL, size_t ln = 0) + : s_exp_element_t(true), + bytes_(bt ? std::vector(bt, bt + ln) : std::vector()){}; + s_exp_block_t(unsigned u); + s_exp_block_t(const std::string &str) + : s_exp_element_t(true), + bytes_((uint8_t *) str.data(), (uint8_t *) (str.data() + str.size())){}; + s_exp_block_t(const pgp_mpi_t &mpi); + unsigned as_unsigned() const noexcept; + bool write(pgp_dest_t &dst) const noexcept; + + const std::vector & + bytes() const + { + return bytes_; + } +}; + +class s_exp_t : public s_exp_element_t { + std::vector> elements_; + /* write s_exp_t contents, adding padding, for the further encryption */ + rnp::secure_vector write_padded(size_t padblock) const; + + public: + s_exp_t() : s_exp_element_t(false){}; + bool parse(const char **r_bytes, size_t *r_length, size_t depth = 1); + void add(std::unique_ptr sptr); + void add(const std::string &str); + void add(const uint8_t *data, size_t size); + void add(unsigned u); + s_exp_t &add_sub(); + bool write(pgp_dest_t &dst) const noexcept; + + size_t + size() const + { + return elements_.size(); + } + + s_exp_element_t & + at(size_t idx) + { + return *elements_[idx].get(); + } + + s_exp_t * lookup_var(const std::string &name) noexcept; + s_exp_block_t *lookup_var_data(const std::string &name) noexcept; + + bool read_mpi(const std::string &name, pgp_mpi_t &val) noexcept; + bool read_curve(const std::string &name, pgp_ec_key_t &key) noexcept; + void add_mpi(const std::string &name, const pgp_mpi_t &val); + void add_curve(const std::string &name, const pgp_ec_key_t &key); + void add_pubkey(const pgp_key_pkt_t &key); + void add_seckey(const pgp_key_pkt_t &key); + void add_protected_seckey(pgp_key_pkt_t & seckey, + const std::string &password, + rnp::RNG & rng); + + void clear(); +}; + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/kbx_blob.hpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/kbx_blob.hpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/kbx_blob.hpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/kbx_blob.hpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE RIBOSE, INC. AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RNP_KBX_BLOB_HPP +#define RNP_KBX_BLOB_HPP + +typedef enum : uint8_t { + KBX_EMPTY_BLOB = 0, + KBX_HEADER_BLOB = 1, + KBX_PGP_BLOB = 2, + KBX_X509_BLOB = 3 +} kbx_blob_type_t; + +class kbx_blob_t { + protected: + kbx_blob_type_t type_; + std::vector image_; + + uint8_t ru8(size_t idx); + uint16_t ru16(size_t idx); + uint32_t ru32(size_t idx); + + public: + virtual ~kbx_blob_t() = default; + kbx_blob_t(std::vector &data); + virtual bool + parse() + { + return true; + }; + + kbx_blob_type_t + type() + { + return type_; + } + + std::vector & + image() + { + return image_; + } + + uint32_t + length() const noexcept + { + return image_.size(); + } +}; + +class kbx_header_blob_t : public kbx_blob_t { + protected: + uint8_t version_{}; + uint16_t flags_{}; + uint32_t file_created_at_{}; + uint32_t last_maintenance_run_{}; + + public: + kbx_header_blob_t(std::vector &data) : kbx_blob_t(data){}; + bool parse(); + + uint32_t + file_created_at() + { + return file_created_at_; + } +}; + +typedef struct { + uint8_t fp[PGP_FINGERPRINT_SIZE]; + uint32_t keyid_offset; + uint16_t flags; +} kbx_pgp_key_t; + +typedef struct { + uint32_t offset; + uint32_t length; + uint16_t flags; + uint8_t validity; +} kbx_pgp_uid_t; + +typedef struct { + uint32_t expired; +} kbx_pgp_sig_t; + +class kbx_pgp_blob_t : public kbx_blob_t { + protected: + uint8_t version_{}; + uint16_t flags_{}; + uint32_t keyblock_offset_{}; + uint32_t keyblock_length_{}; + + std::vector sn_{}; + std::vector keys_{}; + std::vector uids_{}; + std::vector sigs_{}; + + uint8_t ownertrust_{}; + uint8_t all_validity_{}; + + uint32_t recheck_after_{}; + uint32_t latest_timestamp_{}; + uint32_t blob_created_at_{}; + + public: + kbx_pgp_blob_t(std::vector &data) : kbx_blob_t(data){}; + + uint32_t + keyblock_offset() + { + return keyblock_offset_; + } + + uint32_t + keyblock_length() + { + return keyblock_length_; + } + + size_t + nkeys() + { + return keys_.size(); + } + size_t + nuids() + { + return uids_.size(); + } + size_t + nsigs() + { + return sigs_.size(); + } + + bool parse(); +}; + +#endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_g10.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_g10.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_g10.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_g10.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -24,12 +24,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include #include - -#include +#include "config.h" #include #include "key_store_pgp.h" @@ -37,7 +37,9 @@ #include "crypto/common.h" #include "crypto/mem.h" +#include "crypto/cipher.hpp" #include "pgp-key.h" +#include "g10_sexp.hpp" #define G10_CBC_IV_SIZE 16 @@ -51,85 +53,93 @@ pgp_symm_alg_t cipher; pgp_cipher_mode_t cipher_mode; pgp_hash_alg_t hash_alg; - const char * botan_cipher_name; size_t cipher_block_size; const char * g10_type; size_t iv_size; } format_info; -static bool g10_calculated_hash(const pgp_key_pkt_t *key, - const char * protected_at, - uint8_t * checksum); -pgp_key_pkt_t *g10_decrypt_seckey(const uint8_t * data, - size_t data_len, - const pgp_key_pkt_t *pubkey, - const char * password); +static bool g10_calculated_hash(const pgp_key_pkt_t &key, + const char * protected_at, + uint8_t * checksum); static const format_info formats[] = {{PGP_SA_AES_128, PGP_CIPHER_MODE_CBC, PGP_HASH_SHA1, - "AES-128/CBC/NoPadding", 16, "openpgp-s2k3-sha1-aes-cbc", G10_CBC_IV_SIZE}, {PGP_SA_AES_256, PGP_CIPHER_MODE_CBC, PGP_HASH_SHA1, - "AES-256/CBC/NoPadding", 16, "openpgp-s2k3-sha1-aes256-cbc", G10_CBC_IV_SIZE}, {PGP_SA_AES_128, PGP_CIPHER_MODE_OCB, PGP_HASH_SHA1, - "AES-128/OCB/NoPadding", 16, "openpgp-s2k3-ocb-aes", G10_OCB_NONCE_SIZE}}; -static const pgp_map_t g10_alg_aliases[] = {{PGP_PKA_RSA, "rsa"}, - {PGP_PKA_RSA, "openpgp-rsa"}, - {PGP_PKA_RSA, "oid.1.2.840.113549.1.1.1"}, - {PGP_PKA_RSA, "oid.1.2.840.113549.1.1.1"}, - {PGP_PKA_ELGAMAL, "elg"}, - {PGP_PKA_ELGAMAL, "elgamal"}, - {PGP_PKA_ELGAMAL, "openpgp-elg"}, - {PGP_PKA_ELGAMAL, "openpgp-elg-sig"}, - {PGP_PKA_DSA, "dsa"}, - {PGP_PKA_DSA, "openpgp-dsa"}, - {PGP_PKA_ECDSA, "ecc"}, - {PGP_PKA_ECDSA, "ecdsa"}, - {PGP_PKA_ECDH, "ecdh"}, - {PGP_PKA_EDDSA, "eddsa"}}; - -static const pgp_map_t g10_curve_aliases[] = { - {PGP_CURVE_NIST_P_256, "NIST P-256"}, {PGP_CURVE_NIST_P_256, "1.2.840.10045.3.1.7"}, - {PGP_CURVE_NIST_P_256, "prime256v1"}, {PGP_CURVE_NIST_P_256, "secp256r1"}, +static const id_str_pair g10_alg_aliases[] = { + {PGP_PKA_RSA, "rsa"}, + {PGP_PKA_RSA, "openpgp-rsa"}, + {PGP_PKA_RSA, "oid.1.2.840.113549.1.1.1"}, + {PGP_PKA_RSA, "oid.1.2.840.113549.1.1.1"}, + {PGP_PKA_ELGAMAL, "elg"}, + {PGP_PKA_ELGAMAL, "elgamal"}, + {PGP_PKA_ELGAMAL, "openpgp-elg"}, + {PGP_PKA_ELGAMAL, "openpgp-elg-sig"}, + {PGP_PKA_DSA, "dsa"}, + {PGP_PKA_DSA, "openpgp-dsa"}, + {PGP_PKA_ECDSA, "ecc"}, + {PGP_PKA_ECDSA, "ecdsa"}, + {PGP_PKA_ECDH, "ecdh"}, + {PGP_PKA_EDDSA, "eddsa"}, + {0, NULL}, +}; + +static const id_str_pair g10_curve_aliases[] = { + {PGP_CURVE_NIST_P_256, "NIST P-256"}, + {PGP_CURVE_NIST_P_256, "1.2.840.10045.3.1.7"}, + {PGP_CURVE_NIST_P_256, "prime256v1"}, + {PGP_CURVE_NIST_P_256, "secp256r1"}, {PGP_CURVE_NIST_P_256, "nistp256"}, - - {PGP_CURVE_NIST_P_384, "NIST P-384"}, {PGP_CURVE_NIST_P_384, "secp384r1"}, - {PGP_CURVE_NIST_P_384, "1.3.132.0.34"}, {PGP_CURVE_NIST_P_384, "nistp384"}, - - {PGP_CURVE_NIST_P_521, "NIST P-521"}, {PGP_CURVE_NIST_P_521, "secp521r1"}, - {PGP_CURVE_NIST_P_521, "1.3.132.0.35"}, {PGP_CURVE_NIST_P_521, "nistp521"}, - - {PGP_CURVE_25519, "Curve25519"}, {PGP_CURVE_25519, "1.3.6.1.4.1.3029.1.5.1"}, - {PGP_CURVE_ED25519, "Ed25519"}, {PGP_CURVE_ED25519, "1.3.6.1.4.1.11591.15.1"}, - - {PGP_CURVE_BP256, "brainpoolP256r1"}, {PGP_CURVE_BP256, "1.3.36.3.3.2.8.1.1.7"}, - {PGP_CURVE_BP384, "brainpoolP384r1"}, {PGP_CURVE_BP384, "1.3.36.3.3.2.8.1.1.11"}, - {PGP_CURVE_BP512, "brainpoolP512r1"}, {PGP_CURVE_BP512, "1.3.36.3.3.2.8.1.1.13"}, - {PGP_CURVE_P256K1, "secp256k1"}, {PGP_CURVE_P256K1, "1.3.132.0.10"}}; - -static const pgp_map_t g10_curve_names[] = {{PGP_CURVE_NIST_P_256, "NIST P-256"}, - {PGP_CURVE_NIST_P_384, "NIST P-384"}, - {PGP_CURVE_NIST_P_521, "NIST P-521"}, - {PGP_CURVE_ED25519, "Ed25519"}, - {PGP_CURVE_25519, "Curve25519"}, - {PGP_CURVE_BP256, "brainpoolP256r1"}, - {PGP_CURVE_BP384, "brainpoolP384r1"}, - {PGP_CURVE_BP512, "brainpoolP512r1"}, - {PGP_CURVE_P256K1, "secp256k1"}}; + {PGP_CURVE_NIST_P_384, "NIST P-384"}, + {PGP_CURVE_NIST_P_384, "secp384r1"}, + {PGP_CURVE_NIST_P_384, "1.3.132.0.34"}, + {PGP_CURVE_NIST_P_384, "nistp384"}, + {PGP_CURVE_NIST_P_521, "NIST P-521"}, + {PGP_CURVE_NIST_P_521, "secp521r1"}, + {PGP_CURVE_NIST_P_521, "1.3.132.0.35"}, + {PGP_CURVE_NIST_P_521, "nistp521"}, + {PGP_CURVE_25519, "Curve25519"}, + {PGP_CURVE_25519, "1.3.6.1.4.1.3029.1.5.1"}, + {PGP_CURVE_ED25519, "Ed25519"}, + {PGP_CURVE_ED25519, "1.3.6.1.4.1.11591.15.1"}, + {PGP_CURVE_BP256, "brainpoolP256r1"}, + {PGP_CURVE_BP256, "1.3.36.3.3.2.8.1.1.7"}, + {PGP_CURVE_BP384, "brainpoolP384r1"}, + {PGP_CURVE_BP384, "1.3.36.3.3.2.8.1.1.11"}, + {PGP_CURVE_BP512, "brainpoolP512r1"}, + {PGP_CURVE_BP512, "1.3.36.3.3.2.8.1.1.13"}, + {PGP_CURVE_P256K1, "secp256k1"}, + {PGP_CURVE_P256K1, "1.3.132.0.10"}, + {0, NULL}, +}; + +static const id_str_pair g10_curve_names[] = { + {PGP_CURVE_NIST_P_256, "NIST P-256"}, + {PGP_CURVE_NIST_P_384, "NIST P-384"}, + {PGP_CURVE_NIST_P_521, "NIST P-521"}, + {PGP_CURVE_ED25519, "Ed25519"}, + {PGP_CURVE_25519, "Curve25519"}, + {PGP_CURVE_BP256, "brainpoolP256r1"}, + {PGP_CURVE_BP384, "brainpoolP384r1"}, + {PGP_CURVE_BP512, "brainpoolP512r1"}, + {PGP_CURVE_P256K1, "secp256k1"}, + {0, NULL}, +}; static const format_info * find_format(pgp_symm_alg_t cipher, pgp_cipher_mode_t mode, pgp_hash_alg_t hash_alg) @@ -156,80 +166,35 @@ } void -destroy_s_exp(s_exp_t *s_exp) +s_exp_t::add(std::unique_ptr sptr) { - if (s_exp == NULL) { - return; - } - - for (list_item *li = list_front(s_exp->sub_elements); li; li = list_next(li)) { - sub_element_t *sub_el = (sub_element_t *) li; - if (sub_el->is_block) { - free(sub_el->block.bytes); - sub_el->block.bytes = NULL; - sub_el->block.len = 0; - } else { - destroy_s_exp(&sub_el->s_exp); - } - } - list_destroy(&s_exp->sub_elements); + elements_.push_back(std::move(sptr)); } -static bool -add_block_to_sexp(s_exp_t *s_exp, const uint8_t *bytes, size_t len) +void +s_exp_t::add(const std::string &str) { - sub_element_t *sub_el = NULL; - - for (list_item *li = list_front(s_exp->sub_elements); li; li = list_next(li)) { - sub_el = (sub_element_t *) li; - if (sub_el->is_block) { - continue; - } - - if (len == sub_el->block.len && !memcmp(sub_el->block.bytes, bytes, len)) { - // do not duplicate blocks - return true; - } - } - - sub_el = (sub_element_t *) list_append(&s_exp->sub_elements, NULL, sizeof(*sub_el)); - if (!sub_el) { - RNP_LOG("alloc failed"); - return false; - } - - sub_el->is_block = true; - sub_el->block.len = len; - sub_el->block.bytes = (uint8_t *) malloc(len); - if (sub_el->block.bytes == NULL) { - RNP_LOG("can't allocate block memory"); - return false; - } - - memcpy(sub_el->block.bytes, bytes, sub_el->block.len); - return true; + add(std::unique_ptr(new s_exp_block_t(str))); } -static bool -add_string_block_to_sexp(s_exp_t *s_exp, const char *s) +void +s_exp_t::add(const uint8_t *data, size_t size) { - return add_block_to_sexp(s_exp, (uint8_t *) s, strlen(s)); + add(std::unique_ptr(new s_exp_block_t(data, size))); } -static bool -add_sub_sexp_to_sexp(s_exp_t *s_exp, s_exp_t **sub_s_exp) +void +s_exp_t::add(unsigned u) { - sub_element_t *sub_el; - - sub_el = (sub_element_t *) list_append(&s_exp->sub_elements, NULL, sizeof(*sub_el)); - if (!sub_el) { - return false; - } - - sub_el->is_block = false; - *sub_s_exp = &sub_el->s_exp; + add(std::unique_ptr(new s_exp_block_t(u))); +} - return true; +s_exp_t & +s_exp_t::add_sub() +{ + s_exp_t *res = new s_exp_t(); + add(std::unique_ptr(res)); + return *res; } /* @@ -243,14 +208,13 @@ * - a * */ + bool -parse_sexp(s_exp_t *s_exp, const char **r_bytes, size_t *r_length, size_t depth) +s_exp_t::parse(const char **r_bytes, size_t *r_length, size_t depth) { size_t length = *r_length; const char *bytes = *r_bytes; - s_exp_t new_s_exp = {0}; - if (!bytes || !length) { RNP_LOG("empty s-exp"); return true; @@ -271,25 +235,16 @@ do { if (!length) { // unexpected end RNP_LOG("s-exp finished before ')'"); - destroy_s_exp(&new_s_exp); return false; } if (*bytes == '(') { - s_exp_t *new_sub_s_exp; - - if (!add_sub_sexp_to_sexp(&new_s_exp, &new_sub_s_exp)) { + s_exp_t &newsexp = add_sub(); + if (!newsexp.parse(&bytes, &length, depth + 1)) { return false; } - - if (!parse_sexp(new_sub_s_exp, &bytes, &length, depth + 1)) { - destroy_s_exp(&new_s_exp); - return false; - } - if (!length) { RNP_LOG("No space for closing ) left."); - destroy_s_exp(&new_s_exp); return false; } continue; @@ -312,13 +267,11 @@ if (!chars) { RNP_LOG("s-exp contains empty len"); - destroy_s_exp(&new_s_exp); return false; } if (*bytes != ':') { // doesn't contain : RNP_LOG("s-exp doesn't contain ':'"); - destroy_s_exp(&new_s_exp); return false; } @@ -327,251 +280,186 @@ if (!len || len >= length) { RNP_LOG("zero or too large len, len: %zu, length: %zu", len, length); - destroy_s_exp(&new_s_exp); - return false; - } - - if (!add_block_to_sexp(&new_s_exp, (uint8_t *) bytes, len)) { - destroy_s_exp(&new_s_exp); return false; } + add((uint8_t *) bytes, len); bytes += len; length -= len; } while (*bytes != ')'); bytes++; length--; - - *s_exp = new_s_exp; *r_bytes = bytes; *r_length = length; - return true; } +void +s_exp_t::clear() +{ + elements_.clear(); +} + #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) -static unsigned -block_to_unsigned(s_exp_block_t *block) +s_exp_block_t::s_exp_block_t(const pgp_mpi_t &mpi) : s_exp_element_t(true) { - char s[sizeof(STR(UINT_MAX)) + 1] = {0}; - if (!block->len || block->len >= sizeof(s)) { - return UINT_MAX; - } + size_t len = mpi_bytes(&mpi); + size_t idx; + for (idx = 0; (idx < len) && !mpi.mpi[idx]; idx++) + ; - memcpy(s, block->bytes, block->len); - return (unsigned int) atoi(s); + if (idx >= len) { + bytes_ = {0}; + return; + } + if (mpi.mpi[idx] & 0x80) { + bytes_ = std::vector(len - idx + 1); + bytes_[0] = 0; + memcpy(bytes_.data() + 1, mpi.mpi + idx, len - idx); + return; + } + bytes_ = std::vector(mpi.mpi + idx, mpi.mpi + len); } -static bool -add_unsigned_block_to_sexp(s_exp_t *s_exp, unsigned u) +s_exp_block_t::s_exp_block_t(unsigned u) : s_exp_element_t(true) { char s[sizeof(STR(UINT_MAX)) + 1]; snprintf(s, sizeof(s), "%u", u); - return add_block_to_sexp(s_exp, (uint8_t *) s, strlen(s)); + bytes_ = std::vector((uint8_t *) s, (uint8_t *) (s + strlen(s))); } -static size_t -sub_element_count(s_exp_t *s_exp) +unsigned +s_exp_block_t::as_unsigned() const noexcept { - return list_length(s_exp->sub_elements); -} - -static sub_element_t * -sub_element_at(s_exp_t *s_exp, size_t idx) -{ - size_t i = 0; - list_item *item = NULL; - - if (!s_exp || (sub_element_count(s_exp) < idx)) { - return NULL; - } - - for (item = list_front(s_exp->sub_elements); item && (i < idx); item = list_next(item)) { - i++; + char s[sizeof(STR(UINT_MAX)) + 1] = {0}; + if (bytes_.empty() || bytes_.size() >= sizeof(s)) { + return UINT_MAX; } - return (sub_element_t *) item; + memcpy(s, bytes_.data(), bytes_.size()); + return (unsigned) atoi(s); } -static s_exp_t * -lookup_variable(s_exp_t *s_exp, const char *name) +s_exp_t * +s_exp_t::lookup_var(const std::string &name) noexcept { - size_t name_len = strlen(name); - - for (list_item *li = list_front(s_exp->sub_elements); li; li = list_next(li)) { - sub_element_t *name_el = NULL; - sub_element_t *sub_el = (sub_element_t *) li; - - if (sub_el->is_block) { + for (auto &ptr : elements_) { + if (ptr->is_block()) { continue; } - - name_el = sub_element_at(&sub_el->s_exp, 0); - if (sub_element_count(&sub_el->s_exp) < 2 || !name_el || !name_el->is_block) { + s_exp_t &sub_el = dynamic_cast(*ptr.get()); + if ((sub_el.size() < 2) || !sub_el.at(0).is_block()) { RNP_LOG("Expected sub-s-exp with 2 first blocks"); return NULL; } - - if (name_len != name_el->block.len) { + s_exp_block_t &name_el = dynamic_cast(sub_el.at(0)); + if (name_el.bytes().size() != name.size()) { continue; } - - if (!strncmp(name, (const char *) name_el->block.bytes, name_len)) { - return &sub_el->s_exp; + if (!memcmp(name_el.bytes().data(), name.data(), name.size())) { + return &sub_el; } } - RNP_LOG("Haven't got variable '%s'", name); + RNP_LOG("Haven't got variable '%s'", name.c_str()); return NULL; } -static s_exp_block_t * -lookup_variable_data(s_exp_t *s_exp, const char *name) +s_exp_block_t * +s_exp_t::lookup_var_data(const std::string &name) noexcept { - s_exp_t * var = lookup_variable(s_exp, name); - sub_element_t *data = NULL; - + s_exp_t *var = lookup_var(name); if (!var) { return NULL; } - data = sub_element_at(var, 1); - if (!data->is_block) { + if (!var->at(1).is_block()) { RNP_LOG("Expected block value"); return NULL; } - return &data->block; + return dynamic_cast(&var->at(1)); } -static bool -read_mpi(s_exp_t *s_exp, const char *name, pgp_mpi_t *val) +bool +s_exp_t::read_mpi(const std::string &name, pgp_mpi_t &val) noexcept { - s_exp_block_t *data = lookup_variable_data(s_exp, name); - + s_exp_block_t *data = lookup_var_data(name); if (!data) { return false; } /* strip leading zero */ - if ((data->len > 1) && !data->bytes[0] && (data->bytes[1] & 0x80)) { - return mem2mpi(val, data->bytes + 1, data->len - 1); + const auto &bytes = data->bytes(); + if ((bytes.size() > 1) && !bytes[0] && (bytes[1] & 0x80)) { + return mem2mpi(&val, bytes.data() + 1, bytes.size() - 1); } - - return mem2mpi(val, data->bytes, data->len); + return mem2mpi(&val, bytes.data(), bytes.size()); } -static bool -read_curve(s_exp_t *s_exp, const char *name, pgp_ec_key_t *key) +bool +s_exp_t::read_curve(const std::string &name, pgp_ec_key_t &key) noexcept { - s_exp_block_t *data = lookup_variable_data(s_exp, name); - + s_exp_block_t *data = lookup_var_data(name); if (!data) { return false; } - for (size_t i = 0; i < ARRAY_SIZE(g10_curve_aliases); i++) { - if (strlen(g10_curve_aliases[i].string) != data->len) { - continue; - } - if (!memcmp(g10_curve_aliases[i].string, data->bytes, data->len)) { - key->curve = (pgp_curve_t) g10_curve_aliases[i].type; - return true; - } + const auto &bytes = data->bytes(); + pgp_curve_t curve = static_cast( + id_str_pair::lookup(g10_curve_aliases, data->bytes(), PGP_CURVE_UNKNOWN)); + if (curve != PGP_CURVE_UNKNOWN) { + key.curve = curve; + return true; } - - RNP_LOG("Unknown curve: %.*s", (int) data->len, data->bytes); + RNP_LOG("Unknown curve: %.*s", (int) bytes.size(), (char *) bytes.data()); return false; } -static bool -write_mpi(s_exp_t *s_exp, const char *name, const pgp_mpi_t *val) +void +s_exp_t::add_mpi(const std::string &name, const pgp_mpi_t &val) { - uint8_t buf[PGP_MPINT_SIZE + 1] = {0}; - size_t len; - size_t idx; - s_exp_t *sub_s_exp; - - if (!add_sub_sexp_to_sexp(s_exp, &sub_s_exp)) { - return false; - } - - if (!add_string_block_to_sexp(sub_s_exp, name)) { - return false; - } - - len = mpi_bytes(val); - for (idx = 0; (idx < len) && (val->mpi[idx] == 0); idx++) - ; - - if (idx >= len) { - return add_block_to_sexp(sub_s_exp, buf, 1); - } - - if (val->mpi[idx] & 0x80) { - memcpy(buf + 1, val->mpi + idx, len - idx); - return add_block_to_sexp(sub_s_exp, buf, len - idx + 1); - } - - return add_block_to_sexp(sub_s_exp, val->mpi + idx, len - idx); + s_exp_t &sub_s_exp = add_sub(); + sub_s_exp.add(name); + sub_s_exp.add(std::unique_ptr(new s_exp_block_t(val))); } -static bool -write_curve(s_exp_t *s_exp, const char *name, const pgp_ec_key_t *key) +void +s_exp_t::add_curve(const std::string &name, const pgp_ec_key_t &key) { - const char *curve = NULL; - s_exp_t * sub_s_exp; - - ARRAY_LOOKUP_BY_ID(g10_curve_names, type, string, key->curve, curve); + const char *curve = id_str_pair::lookup(g10_curve_names, key.curve, NULL); if (!curve) { RNP_LOG("unknown curve"); - return false; + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - if (!add_sub_sexp_to_sexp(s_exp, &sub_s_exp)) { - return false; - } + s_exp_t *psub_s_exp = &add_sub(); + psub_s_exp->add(name); + psub_s_exp->add(curve); - if (!add_string_block_to_sexp(sub_s_exp, name)) { - return false; - } - - if (!add_string_block_to_sexp(sub_s_exp, curve)) { - return false; - } - - if ((key->curve == PGP_CURVE_ED25519) || (key->curve == PGP_CURVE_25519)) { - if (!add_sub_sexp_to_sexp(s_exp, &sub_s_exp)) { - return false; - } - - if (!add_string_block_to_sexp(sub_s_exp, "flags")) { - return false; - } - - if (!add_string_block_to_sexp( - sub_s_exp, key->curve == PGP_CURVE_ED25519 ? "eddsa" : "djb-tweak")) { - return false; - } + if ((key.curve != PGP_CURVE_ED25519) && (key.curve != PGP_CURVE_25519)) { + return; } - return true; + psub_s_exp = &add_sub(); + psub_s_exp->add("flags"); + psub_s_exp->add((key.curve == PGP_CURVE_ED25519) ? "eddsa" : "djb-tweak"); } static bool -parse_pubkey(pgp_key_pkt_t *pubkey, s_exp_t *s_exp, pgp_pubkey_alg_t alg) +parse_pubkey(pgp_key_pkt_t &pubkey, s_exp_t &s_exp, pgp_pubkey_alg_t alg) { - pubkey->version = PGP_V4; - pubkey->alg = alg; - pubkey->material.alg = alg; + pubkey.version = PGP_V4; + pubkey.alg = alg; + pubkey.material.alg = alg; switch (alg) { case PGP_PKA_DSA: - if (!read_mpi(s_exp, "p", &pubkey->material.dsa.p) || - !read_mpi(s_exp, "q", &pubkey->material.dsa.q) || - !read_mpi(s_exp, "g", &pubkey->material.dsa.g) || - !read_mpi(s_exp, "y", &pubkey->material.dsa.y)) { + if (!s_exp.read_mpi("p", pubkey.material.dsa.p) || + !s_exp.read_mpi("q", pubkey.material.dsa.q) || + !s_exp.read_mpi("g", pubkey.material.dsa.g) || + !s_exp.read_mpi("y", pubkey.material.dsa.y)) { return false; } break; @@ -579,31 +467,31 @@ case PGP_PKA_RSA: case PGP_PKA_RSA_ENCRYPT_ONLY: case PGP_PKA_RSA_SIGN_ONLY: - if (!read_mpi(s_exp, "n", &pubkey->material.rsa.n) || - !read_mpi(s_exp, "e", &pubkey->material.rsa.e)) { + if (!s_exp.read_mpi("n", pubkey.material.rsa.n) || + !s_exp.read_mpi("e", pubkey.material.rsa.e)) { return false; } break; case PGP_PKA_ELGAMAL: case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if (!read_mpi(s_exp, "p", &pubkey->material.eg.p) || - !read_mpi(s_exp, "g", &pubkey->material.eg.g) || - !read_mpi(s_exp, "y", &pubkey->material.eg.y)) { + if (!s_exp.read_mpi("p", pubkey.material.eg.p) || + !s_exp.read_mpi("g", pubkey.material.eg.g) || + !s_exp.read_mpi("y", pubkey.material.eg.y)) { return false; } break; case PGP_PKA_ECDSA: case PGP_PKA_ECDH: case PGP_PKA_EDDSA: - if (!read_curve(s_exp, "curve", &pubkey->material.ec) || - !read_mpi(s_exp, "q", &pubkey->material.ec.p)) { + if (!s_exp.read_curve("curve", pubkey.material.ec) || + !s_exp.read_mpi("q", pubkey.material.ec.p)) { return false; } - if (pubkey->material.ec.curve == PGP_CURVE_ED25519) { + if (pubkey.material.ec.curve == PGP_CURVE_ED25519) { /* need to adjust it here since 'ecc' key type defaults to ECDSA */ - pubkey->alg = PGP_PKA_EDDSA; - pubkey->material.alg = PGP_PKA_EDDSA; + pubkey.alg = PGP_PKA_EDDSA; + pubkey.material.alg = PGP_PKA_EDDSA; } break; default: @@ -615,36 +503,34 @@ } static bool -parse_seckey(pgp_key_pkt_t *seckey, s_exp_t *s_exp, pgp_pubkey_alg_t alg) +parse_seckey(pgp_key_pkt_t &seckey, s_exp_t &s_exp, pgp_pubkey_alg_t alg) { switch (alg) { case PGP_PKA_DSA: - if (!read_mpi(s_exp, "x", &seckey->material.dsa.x)) { + if (!s_exp.read_mpi("x", seckey.material.dsa.x)) { return false; } break; - case PGP_PKA_RSA: case PGP_PKA_RSA_ENCRYPT_ONLY: case PGP_PKA_RSA_SIGN_ONLY: - if (!read_mpi(s_exp, "d", &seckey->material.rsa.d) || - !read_mpi(s_exp, "p", &seckey->material.rsa.p) || - !read_mpi(s_exp, "q", &seckey->material.rsa.q) || - !read_mpi(s_exp, "u", &seckey->material.rsa.u)) { + if (!s_exp.read_mpi("d", seckey.material.rsa.d) || + !s_exp.read_mpi("p", seckey.material.rsa.p) || + !s_exp.read_mpi("q", seckey.material.rsa.q) || + !s_exp.read_mpi("u", seckey.material.rsa.u)) { return false; } break; - case PGP_PKA_ELGAMAL: case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if (!read_mpi(s_exp, "x", &seckey->material.eg.x)) { + if (!s_exp.read_mpi("x", seckey.material.eg.x)) { return false; } break; case PGP_PKA_ECDSA: case PGP_PKA_ECDH: case PGP_PKA_EDDSA: - if (!read_mpi(s_exp, "d", &seckey->material.ec.x)) { + if (!s_exp.read_mpi("d", seckey.material.ec.x)) { return false; } break; @@ -653,301 +539,263 @@ return false; } - seckey->material.secret = true; + seckey.material.secret = true; return true; } static bool -decrypt_protected_section(const uint8_t * encrypted_data, - size_t encrypted_data_len, - const pgp_key_pkt_t *seckey, - const char * password, - s_exp_t * r_s_exp) -{ - const format_info *info = NULL; - unsigned keysize = 0; - uint8_t derived_key[PGP_MAX_KEY_SIZE]; - uint8_t * decrypted_data = NULL; - size_t decrypted_data_len = 0; - size_t output_written = 0; - size_t input_consumed = 0; - botan_cipher_t decrypt = NULL; - bool ret = false; +decrypt_protected_section(const std::vector &encrypted_data, + const pgp_key_pkt_t & seckey, + const std::string & password, + s_exp_t & r_s_exp) +{ + const format_info * info = NULL; + unsigned keysize = 0; + uint8_t derived_key[PGP_MAX_KEY_SIZE]; + uint8_t * decrypted_data = NULL; + size_t decrypted_data_len = 0; + size_t output_written = 0; + size_t input_consumed = 0; + std::unique_ptr dec; + bool ret = false; const char *decrypted_bytes; size_t s_exp_len; // sanity checks - const pgp_key_protection_t *prot = &seckey->sec_protection; - keysize = pgp_key_size(prot->symm_alg); + const pgp_key_protection_t &prot = seckey.sec_protection; + keysize = pgp_key_size(prot.symm_alg); if (!keysize) { RNP_LOG("parse_seckey: unknown symmetric algo"); goto done; } // find the protection format in our table - info = find_format(prot->symm_alg, prot->cipher_mode, prot->s2k.hash_alg); + info = find_format(prot.symm_alg, prot.cipher_mode, prot.s2k.hash_alg); if (!info) { RNP_LOG("Unsupported format, alg: %d, chiper_mode: %d, hash: %d", - prot->symm_alg, - prot->cipher_mode, - prot->s2k.hash_alg); + prot.symm_alg, + prot.cipher_mode, + prot.s2k.hash_alg); goto done; } // derive the key - if (pgp_s2k_iterated(prot->s2k.hash_alg, + if (pgp_s2k_iterated(prot.s2k.hash_alg, derived_key, keysize, - password, - prot->s2k.salt, - prot->s2k.iterations)) { + password.c_str(), + prot.s2k.salt, + prot.s2k.iterations)) { RNP_LOG("pgp_s2k_iterated failed"); goto done; } - RNP_DHEX("input iv", prot->iv, G10_CBC_IV_SIZE); - RNP_DHEX("key", derived_key, keysize); - RNP_DHEX("encrypted", encrypted_data, encrypted_data_len); // decrypt - decrypted_data = (uint8_t *) malloc(encrypted_data_len); + decrypted_data = (uint8_t *) malloc(encrypted_data.size()); if (decrypted_data == NULL) { RNP_LOG("can't allocate memory"); goto done; } - if (botan_cipher_init(&decrypt, info->botan_cipher_name, BOTAN_CIPHER_INIT_FLAG_DECRYPT)) { - RNP_LOG("botan_cipher_init failed"); - goto done; - } - if (botan_cipher_set_key(decrypt, derived_key, keysize) || - botan_cipher_start(decrypt, prot->iv, info->iv_size)) { + dec = Cipher::decryption(info->cipher, info->cipher_mode, 0, true); + if (!dec || !dec->set_key(derived_key, keysize) || !dec->set_iv(prot.iv, info->iv_size)) { goto done; } - if (botan_cipher_update(decrypt, - BOTAN_CIPHER_UPDATE_FLAG_FINAL, - decrypted_data, - encrypted_data_len, - &output_written, - encrypted_data, - encrypted_data_len, - &input_consumed)) { - RNP_LOG("botan_cipher_update failed"); + if (!dec->finish(decrypted_data, + encrypted_data.size(), + &output_written, + encrypted_data.data(), + encrypted_data.size(), + &input_consumed)) { goto done; } decrypted_data_len = output_written; s_exp_len = decrypted_data_len; decrypted_bytes = (const char *) decrypted_data; - RNP_DHEX("decrypted data", decrypted_data, decrypted_data_len); // parse and validate the decrypted s-exp - if (!parse_sexp(r_s_exp, &decrypted_bytes, &s_exp_len)) { + if (!r_s_exp.parse(&decrypted_bytes, &s_exp_len)) { goto done; } - if (!sub_element_count(r_s_exp) || sub_element_at(r_s_exp, 0)->is_block) { + if (!r_s_exp.size() || r_s_exp.at(0).is_block()) { RNP_LOG("Hasn't got sub s-exp with key data."); goto done; } - ret = true; - done: if (!ret) { - destroy_s_exp(r_s_exp); + r_s_exp.clear(); } secure_clear(decrypted_data, decrypted_data_len); free(decrypted_data); - botan_cipher_destroy(decrypt); return ret; } static bool -parse_protected_seckey(pgp_key_pkt_t *seckey, s_exp_t *s_exp, const char *password) +parse_protected_seckey(pgp_key_pkt_t &seckey, s_exp_t &s_exp, const char *password) { - const format_info * format; - bool ret = false; - s_exp_t decrypted_s_exp = {0}; - s_exp_t * alg = NULL; - s_exp_t * params = NULL; - s_exp_block_t * protected_at_data = NULL; - sub_element_t * sub_el = NULL; - pgp_key_protection_t *prot; - // find and validate the protected section - s_exp_t *protected_key = lookup_variable(s_exp, "protected"); + s_exp_t *protected_key = s_exp.lookup_var("protected"); if (!protected_key) { RNP_LOG("missing protected section"); - goto done; + return false; } - if (sub_element_count(protected_key) != 4 || !sub_element_at(protected_key, 1)->is_block || - sub_element_at(protected_key, 2)->is_block || - !sub_element_at(protected_key, 3)->is_block) { + if (protected_key->size() != 4 || !protected_key->at(1).is_block() || + protected_key->at(2).is_block() || !protected_key->at(3).is_block()) { RNP_LOG("Wrong protected format, expected: (protected mode (parms) " "encrypted_octet_string)\n"); - goto done; + return false; } // lookup the protection format - sub_el = sub_element_at(protected_key, 1); - format = parse_format((const char *) sub_el->block.bytes, sub_el->block.len); - if (format == NULL) { + auto & fmt_bt = (dynamic_cast(protected_key->at(1))).bytes(); + const format_info *format = parse_format((const char *) fmt_bt.data(), fmt_bt.size()); + if (!format) { RNP_LOG("Unsupported protected mode: '%.*s'\n", - (int) sub_el->block.len, - sub_el->block.bytes); - goto done; + (int) fmt_bt.size(), + (const char *) fmt_bt.data()); + return false; } // fill in some fields based on the lookup above - prot = &seckey->sec_protection; - prot->symm_alg = format->cipher; - prot->cipher_mode = format->cipher_mode; - prot->s2k.hash_alg = format->hash_alg; + pgp_key_protection_t &prot = seckey.sec_protection; + prot.symm_alg = format->cipher; + prot.cipher_mode = format->cipher_mode; + prot.s2k.hash_alg = format->hash_alg; // locate and validate the protection parameters - params = &sub_element_at(protected_key, 2)->s_exp; - if (sub_element_count(params) != 2 || sub_element_at(params, 0)->is_block || - !sub_element_at(params, 1)->is_block) { + s_exp_t ¶ms = dynamic_cast(protected_key->at(2)); + if (params.size() != 2 || params.at(0).is_block() || !params.at(1).is_block()) { RNP_LOG("Wrong params format, expected: ((hash salt no_of_iterations) iv)\n"); - goto done; + return false; } // locate and validate the (hash salt no_of_iterations) exp - alg = &sub_element_at(params, 0)->s_exp; - if (sub_element_count(alg) != 3 || !sub_element_at(alg, 0)->is_block || - !sub_element_at(alg, 1)->is_block || !sub_element_at(alg, 2)->is_block) { + s_exp_t &alg = dynamic_cast(params.at(0)); + if (alg.size() != 3 || !alg.at(0).is_block() || !alg.at(1).is_block() || + !alg.at(2).is_block()) { RNP_LOG("Wrong params sub-level format, expected: (hash salt no_of_iterations)\n"); - goto done; + return false; } - sub_el = sub_element_at(alg, 0); - if ((sub_el->block.len != 4) || memcmp("sha1", sub_el->block.bytes, 4)) { + auto &hash_bt = (dynamic_cast(alg.at(0))).bytes(); + if ((hash_bt.size() != 4) || memcmp("sha1", hash_bt.data(), 4)) { RNP_LOG("Wrong hashing algorithm, should be sha1 but %.*s\n", - (int) sub_el->block.len, - sub_el->block.bytes); - goto done; + (int) hash_bt.size(), + (const char *) hash_bt.data()); + return false; } // fill in some constant values - prot->s2k.hash_alg = PGP_HASH_SHA1; - prot->s2k.usage = PGP_S2KU_ENCRYPTED_AND_HASHED; - prot->s2k.specifier = PGP_S2KS_ITERATED_AND_SALTED; + prot.s2k.hash_alg = PGP_HASH_SHA1; + prot.s2k.usage = PGP_S2KU_ENCRYPTED_AND_HASHED; + prot.s2k.specifier = PGP_S2KS_ITERATED_AND_SALTED; // check salt size - sub_el = sub_element_at(alg, 1); - if (sub_el->block.len != PGP_SALT_SIZE) { - RNP_LOG( - "Wrong salt size, should be %d but %d\n", PGP_SALT_SIZE, (int) sub_el->block.len); - goto done; + auto &salt_bt = (dynamic_cast(alg.at(1))).bytes(); + if (salt_bt.size() != PGP_SALT_SIZE) { + RNP_LOG("Wrong salt size, should be %d but %d\n", PGP_SALT_SIZE, (int) salt_bt.size()); + return false; } // salt - memcpy(prot->s2k.salt, sub_el->block.bytes, sub_el->block.len); + memcpy(prot.s2k.salt, salt_bt.data(), salt_bt.size()); // s2k iterations - sub_el = sub_element_at(alg, 2); - prot->s2k.iterations = block_to_unsigned(&sub_el->block); - if (prot->s2k.iterations == UINT_MAX) { - RNP_LOG( - "Wrong numbers of iteration, %.*s\n", (int) sub_el->block.len, sub_el->block.bytes); - goto done; + auto &iter = dynamic_cast(alg.at(2)); + prot.s2k.iterations = iter.as_unsigned(); + if (prot.s2k.iterations == UINT_MAX) { + RNP_LOG("Wrong numbers of iteration, %.*s\n", + (int) iter.bytes().size(), + (const char *) iter.bytes().data()); + return false; } // iv - sub_el = sub_element_at(params, 1); - if (sub_el->block.len != format->iv_size) { - RNP_LOG("Wrong nonce size, should be %zu but %d\n", - format->iv_size, - (int) sub_el->block.len); - goto done; + auto &iv_bt = (dynamic_cast(params.at(1))).bytes(); + if (iv_bt.size() != format->iv_size) { + RNP_LOG("Wrong nonce size, should be %zu but %zu\n", format->iv_size, iv_bt.size()); + return false; } - memcpy(prot->iv, sub_el->block.bytes, sub_el->block.len); + memcpy(prot.iv, iv_bt.data(), iv_bt.size()); // we're all done if no password was provided (decryption not requested) if (!password) { - seckey->material.secret = false; - ret = true; - goto done; + seckey.material.secret = false; + return true; } // password was provided, so decrypt - sub_el = sub_element_at(protected_key, 3); - if (!decrypt_protected_section( - sub_el->block.bytes, sub_el->block.len, seckey, password, &decrypted_s_exp)) { - goto done; + auto & enc_bt = (dynamic_cast(protected_key->at(3))).bytes(); + s_exp_t decrypted_s_exp; + if (!decrypt_protected_section(enc_bt, seckey, password, decrypted_s_exp)) { + return false; } // see if we have a protected-at section - protected_at_data = lookup_variable_data(s_exp, "protected-at"); - char protected_at[G10_PROTECTED_AT_SIZE]; + char protected_at[G10_PROTECTED_AT_SIZE] = {0}; + s_exp_block_t *protected_at_data = s_exp.lookup_var_data("protected-at"); if (protected_at_data) { - if (protected_at_data->len != G10_PROTECTED_AT_SIZE) { + if (protected_at_data->bytes().size() != G10_PROTECTED_AT_SIZE) { RNP_LOG("protected-at has wrong length: %zu, expected, %d\n", - protected_at_data->len, + protected_at_data->bytes().size(), G10_PROTECTED_AT_SIZE); - goto done; + return false; } - memcpy(protected_at, protected_at_data->bytes, protected_at_data->len); + memcpy( + protected_at, protected_at_data->bytes().data(), protected_at_data->bytes().size()); } // parse MPIs - if (!parse_seckey(seckey, &sub_element_at(&decrypted_s_exp, 0)->s_exp, seckey->alg)) { + if (!parse_seckey(seckey, dynamic_cast(decrypted_s_exp.at(0)), seckey.alg)) { RNP_LOG("failed to parse seckey"); - goto done; + return false; } // check hash, if present - if (sub_element_count(&decrypted_s_exp) > 1) { - sub_el = sub_element_at(&decrypted_s_exp, 1); - if (sub_el->is_block || sub_element_count(&sub_el->s_exp) < 3 || - !sub_element_at(&sub_el->s_exp, 0)->is_block || - !sub_element_at(&sub_el->s_exp, 1)->is_block || - !sub_element_at(&sub_el->s_exp, 2)->is_block || - (sub_element_at(&sub_el->s_exp, 0)->block.len != 4) || - memcmp("hash", sub_element_at(&sub_el->s_exp, 0)->block.bytes, 4)) { - RNP_LOG("Has got wrong hash block at encrypted key data."); - goto done; + if (decrypted_s_exp.size() > 1) { + if (decrypted_s_exp.at(1).is_block()) { + RNP_LOG("Wrong hash block type."); + return false; + } + auto &sub_el = dynamic_cast(decrypted_s_exp.at(1)); + if (sub_el.size() < 3 || !sub_el.at(0).is_block() || !sub_el.at(1).is_block() || + !sub_el.at(2).is_block()) { + RNP_LOG("Wrong hash block structure."); + return false; } - if ((sub_element_at(&sub_el->s_exp, 1)->block.len != 4) || - memcmp("sha1", sub_element_at(&sub_el->s_exp, 1)->block.bytes, 4)) { + auto &hkey = (dynamic_cast(sub_el.at(0))).bytes(); + if ((hkey.size() != 4) || memcmp("hash", hkey.data(), 4)) { + RNP_LOG("Has got wrong hash block at encrypted key data."); + return false; + } + auto &halg = (dynamic_cast(sub_el.at(1))).bytes(); + if ((halg.size() != 4) || memcmp("sha1", halg.data(), 4)) { RNP_LOG("Supported only sha1 hash at encrypted private key."); - goto done; + return false; } - uint8_t checkhash[G10_SHA1_HASH_SIZE]; if (!g10_calculated_hash(seckey, protected_at, checkhash)) { RNP_LOG("failed to calculate hash"); - goto done; + return false; } - - sub_el = sub_element_at(&sub_el->s_exp, 2); - if (sub_el->block.len != G10_SHA1_HASH_SIZE || - memcmp(checkhash, sub_el->block.bytes, G10_SHA1_HASH_SIZE) != 0) { - RNP_DHEX("Expected hash", checkhash, G10_SHA1_HASH_SIZE); - RNP_DHEX("Has hash", sub_el->block.bytes, sub_el->block.len); + auto &hval = (dynamic_cast(sub_el.at(2))).bytes(); + if (hval.size() != G10_SHA1_HASH_SIZE || + memcmp(checkhash, hval.data(), G10_SHA1_HASH_SIZE)) { RNP_LOG("Incorrect hash at encrypted private key."); - goto done; + return false; } } - seckey->material.secret = true; - ret = true; - -done: - destroy_s_exp(&decrypted_s_exp); - return ret; + seckey.material.secret = true; + return true; } static bool -g10_parse_seckey(pgp_key_pkt_t *seckey, +g10_parse_seckey(pgp_key_pkt_t &seckey, const uint8_t *data, size_t data_len, const char * password) { - s_exp_t s_exp = {0}; - bool ret = false; - pgp_pubkey_alg_t alg = PGP_PKA_NOTHING; - s_exp_t * algorithm_s_exp = NULL; - s_exp_block_t * block = NULL; - bool is_protected = false; - - RNP_DHEX("S-exp", (const uint8_t *) data, data_len); - + s_exp_t s_exp; const char *bytes = (const char *) data; - if (!parse_sexp(&s_exp, &bytes, &data_len)) { - goto done; + if (!s_exp.parse(&bytes, &data_len)) { + RNP_LOG("Failed to parse s-exp."); + return false; } /* expected format: @@ -959,106 +807,89 @@ * ) */ - if (sub_element_count(&s_exp) != 2 || !sub_element_at(&s_exp, 0)->is_block || - sub_element_at(&s_exp, 1)->is_block) { + if (s_exp.size() != 2 || !s_exp.at(0).is_block() || s_exp.at(1).is_block()) { RNP_LOG("Wrong format, expected: ( (...))"); - goto done; + return false; } - block = &sub_element_at(&s_exp, 0)->block; - if ((block->len == 11) && !memcmp("private-key", block->bytes, block->len)) { + bool is_protected = false; + auto &name = (dynamic_cast(s_exp.at(0))).bytes(); + if ((name.size() == 11) && !memcmp("private-key", name.data(), name.size())) { is_protected = false; - } else if ((block->len == 21) && - !memcmp("protected-private-key", block->bytes, block->len)) { + } else if ((name.size() == 21) && + !memcmp("protected-private-key", name.data(), name.size())) { is_protected = true; } else { - RNP_LOG("Unsupported top-level block: '%.*s'", (int) block->len, block->bytes); - goto done; + RNP_LOG("Unsupported top-level block: '%.*s'", + (int) name.size(), + (const char *) name.data()); + return false; } - algorithm_s_exp = &sub_element_at(&s_exp, 1)->s_exp; - - if (sub_element_count(algorithm_s_exp) < 2) { - RNP_LOG("Wrong count of algorithm-level elements: %d, should great than 1", - (int) sub_element_count(algorithm_s_exp)); - goto done; + s_exp_t &alg_s_exp = dynamic_cast(s_exp.at(1)); + if (alg_s_exp.size() < 2) { + RNP_LOG("Wrong count of algorithm-level elements: %zu", alg_s_exp.size()); + return false; } - if (!sub_element_at(algorithm_s_exp, 0)->is_block) { + if (!alg_s_exp.at(0).is_block()) { RNP_LOG("Expected block with algorithm name, but has s-exp"); - goto done; - } - - block = &sub_element_at(algorithm_s_exp, 0)->block; - alg = PGP_PKA_NOTHING; - for (size_t i = 0; i < ARRAY_SIZE(g10_alg_aliases); i++) { - if (strlen(g10_alg_aliases[i].string) != block->len) { - continue; - } - if (!memcmp(g10_alg_aliases[i].string, block->bytes, block->len)) { - alg = (pgp_pubkey_alg_t) g10_alg_aliases[i].type; - break; - } + return false; } + auto & alg_bt = (dynamic_cast(alg_s_exp.at(0))).bytes(); + pgp_pubkey_alg_t alg = static_cast( + id_str_pair::lookup(g10_alg_aliases, alg_bt, PGP_PKA_NOTHING)); if (alg == PGP_PKA_NOTHING) { - RNP_LOG("Unsupported algorithm: '%.*s'", (int) block->len, block->bytes); - goto done; + RNP_LOG( + "Unsupported algorithm: '%.*s'", (int) alg_bt.size(), (const char *) alg_bt.data()); + return false; } - if (!parse_pubkey(seckey, algorithm_s_exp, alg)) { + bool ret = false; + if (!parse_pubkey(seckey, alg_s_exp, alg)) { RNP_LOG("failed to parse pubkey"); goto done; } if (is_protected) { - if (!parse_protected_seckey(seckey, algorithm_s_exp, password)) { + if (!parse_protected_seckey(seckey, alg_s_exp, password)) { goto done; } } else { - seckey->sec_protection.s2k.usage = PGP_S2KU_NONE; - seckey->sec_protection.symm_alg = PGP_SA_PLAINTEXT; - seckey->sec_protection.s2k.hash_alg = PGP_HASH_UNKNOWN; - if (!parse_seckey(seckey, algorithm_s_exp, alg)) { + seckey.sec_protection.s2k.usage = PGP_S2KU_NONE; + seckey.sec_protection.symm_alg = PGP_SA_PLAINTEXT; + seckey.sec_protection.s2k.hash_alg = PGP_HASH_UNKNOWN; + if (!parse_seckey(seckey, alg_s_exp, alg)) { RNP_LOG("failed to parse seckey"); goto done; } } - - if (rnp_get_debug(__FILE__)) { - pgp_key_grip_t grip; - char grips[PGP_KEY_GRIP_SIZE * 3]; - if (rnp_key_store_get_key_grip(&seckey->material, grip)) { - RNP_LOG("loaded G10 key with GRIP: %s\n", - rnp_strhexdump_upper(grips, grip.data(), grip.size(), "")); - } - } ret = true; - done: - destroy_s_exp(&s_exp); if (!ret) { - *seckey = pgp_key_pkt_t(); + seckey = pgp_key_pkt_t(); } return ret; } pgp_key_pkt_t * -g10_decrypt_seckey(const uint8_t * data, - size_t data_len, - const pgp_key_pkt_t *pubkey, - const char * password) +g10_decrypt_seckey(const pgp_rawpacket_t &raw, + const pgp_key_pkt_t & pubkey, + const char * password) { if (!password) { return NULL; } - - pgp_key_pkt_t *seckey = pubkey ? new pgp_key_pkt_t(*pubkey, false) : new pgp_key_pkt_t(); - if (!g10_parse_seckey(seckey, data, data_len, password)) { - delete seckey; + auto seckey = std::unique_ptr(new pgp_key_pkt_t(pubkey, false)); + if (!g10_parse_seckey(*seckey, raw.raw.data(), raw.raw.size(), password)) { return NULL; } - return seckey; + /* g10 has the same 'ecc' algo for ECDSA/ECDH/EDDSA. Probably should be better place to fix + * this. */ + seckey->alg = pubkey.alg; + seckey->material.alg = pubkey.material.alg; + return seckey.release(); } static bool @@ -1113,7 +944,7 @@ /* parse secret key: fills material and sec_protection only */ if (!g10_parse_seckey( - &seckey, (uint8_t *) mem_src_get_memory(&memsrc), memsrc.size, NULL)) { + seckey, (uint8_t *) mem_src_get_memory(&memsrc), memsrc.size, NULL)) { goto done; } @@ -1168,16 +999,14 @@ #define MAX_SIZE_T_LEN ((3 * sizeof(size_t) * CHAR_BIT / 8) + 2) -static bool -write_block(s_exp_block_t *block, pgp_dest_t *dst) +bool +s_exp_block_t::write(pgp_dest_t &dst) const noexcept { char blen[MAX_SIZE_T_LEN + 1] = {0}; - size_t len; - - len = snprintf(blen, sizeof(blen), "%zu:", block->len); - dst_write(dst, blen, len); - dst_write(dst, block->bytes, block->len); - return dst->werr == RNP_SUCCESS; + size_t len = snprintf(blen, sizeof(blen), "%zu:", bytes_.size()); + dst_write(&dst, blen, len); + dst_write(&dst, bytes_.data(), bytes_.size()); + return dst.werr == RNP_SUCCESS; } /* @@ -1185,273 +1014,234 @@ * * Supported format: (1:a2:ab(3:asd1:a)) */ -static bool -write_sexp(s_exp_t *s_exp, pgp_dest_t *dst) +bool +s_exp_t::write(pgp_dest_t &dst) const noexcept { - dst_write(dst, "(", 1); - if (dst->werr != RNP_SUCCESS) { + dst_write(&dst, "(", 1); + if (dst.werr) { return false; } - for (list_item *item = list_front(s_exp->sub_elements); item; item = list_next(item)) { - sub_element_t *sub_el = (sub_element_t *) item; - - if (sub_el->is_block) { - if (!write_block(&sub_el->block, dst)) { - return false; - } - } else { - if (!write_sexp(&sub_el->s_exp, dst)) { - return false; - } + for (auto &ptr : elements_) { + if (!ptr->write(dst)) { + return false; } } - dst_write(dst, ")", 1); - return dst->werr == RNP_SUCCESS; + dst_write(&dst, ")", 1); + return !dst.werr; } -static bool -write_pubkey(s_exp_t *s_exp, const pgp_key_pkt_t *key) +void +s_exp_t::add_pubkey(const pgp_key_pkt_t &key) { - const pgp_key_material_t *kmaterial = &key->material; - switch (key->alg) { + switch (key.alg) { case PGP_PKA_DSA: - if (!add_string_block_to_sexp(s_exp, "dsa")) { - return false; - } - if (!write_mpi(s_exp, "p", &kmaterial->dsa.p) || - !write_mpi(s_exp, "q", &kmaterial->dsa.q) || - !write_mpi(s_exp, "g", &kmaterial->dsa.g) || - !write_mpi(s_exp, "y", &kmaterial->dsa.y)) { - return false; - } + add("dsa"); + add_mpi("p", key.material.dsa.p); + add_mpi("q", key.material.dsa.q); + add_mpi("g", key.material.dsa.g); + add_mpi("y", key.material.dsa.y); break; case PGP_PKA_RSA_SIGN_ONLY: case PGP_PKA_RSA_ENCRYPT_ONLY: case PGP_PKA_RSA: - if (!add_string_block_to_sexp(s_exp, "rsa")) { - return false; - } - if (!write_mpi(s_exp, "n", &kmaterial->rsa.n) || - !write_mpi(s_exp, "e", &kmaterial->rsa.e)) { - return false; - } + add("rsa"); + add_mpi("n", key.material.rsa.n); + add_mpi("e", key.material.rsa.e); break; case PGP_PKA_ELGAMAL: - if (!add_string_block_to_sexp(s_exp, "elg")) { - return false; - } - if (!write_mpi(s_exp, "p", &kmaterial->eg.p) || - !write_mpi(s_exp, "g", &kmaterial->eg.g) || - !write_mpi(s_exp, "y", &kmaterial->eg.y)) { - return false; - } + add("elg"); + add_mpi("p", key.material.eg.p); + add_mpi("g", key.material.eg.g); + add_mpi("y", key.material.eg.y); break; case PGP_PKA_ECDSA: case PGP_PKA_ECDH: case PGP_PKA_EDDSA: - if (!add_string_block_to_sexp(s_exp, "ecc")) { - return false; - } - if (!write_curve(s_exp, "curve", &kmaterial->ec) || - !write_mpi(s_exp, "q", &kmaterial->ec.p)) { - return false; - } + add("ecc"); + add_curve("curve", key.material.ec); + add_mpi("q", key.material.ec.p); break; default: - RNP_LOG("Unsupported public key algorithm: %d", (int) key->alg); - return false; + RNP_LOG("Unsupported public key algorithm: %d", (int) key.alg); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - - return true; } -static bool -write_seckey(s_exp_t *s_exp, const pgp_key_pkt_t *key) +void +s_exp_t::add_seckey(const pgp_key_pkt_t &key) { - switch (key->alg) { + switch (key.alg) { case PGP_PKA_DSA: - if (!write_mpi(s_exp, "x", &key->material.dsa.x)) { - return false; - } + add_mpi("x", key.material.dsa.x); break; case PGP_PKA_RSA_SIGN_ONLY: case PGP_PKA_RSA_ENCRYPT_ONLY: case PGP_PKA_RSA: - if (!write_mpi(s_exp, "d", &key->material.rsa.d) || - !write_mpi(s_exp, "p", &key->material.rsa.p) || - !write_mpi(s_exp, "q", &key->material.rsa.q) || - !write_mpi(s_exp, "u", &key->material.rsa.u)) { - return false; - } + add_mpi("d", key.material.rsa.d); + add_mpi("p", key.material.rsa.p); + add_mpi("q", key.material.rsa.q); + add_mpi("u", key.material.rsa.u); break; case PGP_PKA_ELGAMAL: - if (!write_mpi(s_exp, "x", &key->material.eg.x)) { - return false; - } + add_mpi("x", key.material.eg.x); break; case PGP_PKA_ECDSA: case PGP_PKA_ECDH: case PGP_PKA_EDDSA: { - if (!write_mpi(s_exp, "d", &key->material.ec.x)) { - return false; - } + add_mpi("d", key.material.ec.x); break; } default: - RNP_LOG("Unsupported public key algorithm: %d", (int) key->alg); - return false; + RNP_LOG("Unsupported public key algorithm: %d", (int) key.alg); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - - return true; } -static bool -write_protected_seckey(s_exp_t *s_exp, pgp_key_pkt_t *seckey, const char *password) +rnp::secure_vector +s_exp_t::write_padded(size_t padblock) const { - bool ret = false; - const format_info * format; - s_exp_t raw_s_exp = {0}; - s_exp_t * sub_s_exp, *sub_sub_s_exp, *sub_sub_sub_s_exp; - pgp_dest_t raw = {0}; - uint8_t * encrypted_data = NULL; - botan_cipher_t encrypt = NULL; - unsigned keysize; - uint8_t checksum[G10_SHA1_HASH_SIZE]; - uint8_t derived_key[PGP_MAX_KEY_SIZE]; - pgp_key_protection_t *prot = &seckey->sec_protection; - size_t encrypted_data_len = 0; - size_t output_written, input_consumed; - - if (prot->s2k.specifier != PGP_S2KS_ITERATED_AND_SALTED) { - return false; - } - format = find_format(prot->symm_alg, prot->cipher_mode, prot->s2k.hash_alg); - if (format == NULL) { - return false; - } - - // randomize IV and salt - rng_t rng = {0}; - if (!rng_init(&rng, RNG_SYSTEM) || !rng_get_data(&rng, &prot->iv[0], sizeof(prot->iv)) || - !rng_get_data(&rng, &prot->s2k.salt[0], sizeof(prot->s2k.salt))) { - rng_destroy(&rng); - RNP_LOG("iv generation failed"); - return false; - } - rng_destroy(&rng); - + pgp_dest_t raw = {0}; if (init_mem_dest(&raw, NULL, 0)) { RNP_LOG("mem dst alloc failed"); - return false; + throw rnp::rnp_exception(RNP_ERROR_OUT_OF_MEMORY); } + mem_dest_secure_memory(&raw, true); - if (!add_sub_sexp_to_sexp(&raw_s_exp, &sub_s_exp) || !write_seckey(sub_s_exp, seckey)) { - RNP_LOG("failed to write seckey"); - goto done; - } + try { + if (!write(raw)) { + RNP_LOG("failed to serialize s_exp"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } - // calculated hash - time_t now; - time(&now); - char protected_at[G10_PROTECTED_AT_SIZE + 1]; - // TODO: how critical is it if we have a skewed timestamp here due to y2k38 problem? - strftime(protected_at, sizeof(protected_at), "%Y%m%dT%H%M%S", gmtime(&now)); + // add padding! + size_t padding = padblock - raw.writeb % padblock; + for (size_t i = 0; i < padding; i++) { + dst_write(&raw, "X", 1); + } + if (raw.werr) { + RNP_LOG("failed to write padding"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } - if (!g10_calculated_hash(seckey, protected_at, checksum) || - !add_sub_sexp_to_sexp(&raw_s_exp, &sub_s_exp) || - !add_string_block_to_sexp(sub_s_exp, "hash") || - !add_string_block_to_sexp(sub_s_exp, "sha1") || - !add_block_to_sexp(sub_s_exp, checksum, sizeof(checksum)) || - !write_sexp(&raw_s_exp, &raw)) { - goto done; + uint8_t * mem = (uint8_t *) mem_dest_get_memory(&raw); + rnp::secure_vector res(mem, mem + raw.writeb); + dst_close(&raw, true); + return res; + } catch (const std::exception &e) { + dst_close(&raw, true); + throw; } +} - keysize = pgp_key_size(prot->symm_alg); - if (keysize == 0) { - goto done; +void +s_exp_t::add_protected_seckey(pgp_key_pkt_t & seckey, + const std::string &password, + rnp::RNG & rng) +{ + pgp_key_protection_t &prot = seckey.sec_protection; + if (prot.s2k.specifier != PGP_S2KS_ITERATED_AND_SALTED) { + RNP_LOG("Bad s2k specifier: %d", (int) prot.s2k.specifier); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + const format_info *format = + find_format(prot.symm_alg, prot.cipher_mode, prot.s2k.hash_alg); + if (!format) { + RNP_LOG("Unknown protection format."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - if (pgp_s2k_iterated(format->hash_alg, - derived_key, - keysize, - (const char *) password, - prot->s2k.salt, - prot->s2k.iterations)) { - goto done; - } + // randomize IV and salt + rng.get(prot.iv, sizeof(prot.iv)); + rng.get(prot.s2k.salt, sizeof(prot.s2k.salt)); - // add padding! - for (int i = (int) (format->cipher_block_size - raw.writeb % format->cipher_block_size); - i > 0; - i--) { - dst_write(&raw, "X", 1); - if (raw.werr != RNP_SUCCESS) { - goto done; - } - } + // write seckey + s_exp_t raw_s_exp; + s_exp_t *psub_s_exp = &raw_s_exp.add_sub(); + psub_s_exp->add_seckey(seckey); - encrypted_data_len = raw.writeb; - encrypted_data = (uint8_t *) malloc(encrypted_data_len); - if (!encrypted_data) { - goto done; + // calculate hash + time_t now; + time(&now); + char protected_at[G10_PROTECTED_AT_SIZE + 1]; + uint8_t checksum[G10_SHA1_HASH_SIZE]; + // TODO: how critical is it if we have a skewed timestamp here due to y2k38 problem? + strftime(protected_at, sizeof(protected_at), "%Y%m%dT%H%M%S", gmtime(&now)); + if (!g10_calculated_hash(seckey, protected_at, checksum)) { + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); } - RNP_DHEX("input iv", prot->iv, G10_CBC_IV_SIZE); - RNP_DHEX("key", derived_key, keysize); - RNP_DHEX("raw data", (uint8_t *) mem_dest_get_memory(&raw), raw.writeb); - - if (botan_cipher_init( - &encrypt, format->botan_cipher_name, BOTAN_CIPHER_INIT_FLAG_ENCRYPT) || - botan_cipher_set_key(encrypt, derived_key, keysize) || - botan_cipher_start(encrypt, prot->iv, format->iv_size)) { - goto done; - } - if (botan_cipher_update(encrypt, - BOTAN_CIPHER_UPDATE_FLAG_FINAL, - encrypted_data, - encrypted_data_len, - &output_written, - (uint8_t *) mem_dest_get_memory(&raw), - raw.writeb, - &input_consumed)) { - goto done; - } + psub_s_exp = &raw_s_exp.add_sub(); + psub_s_exp->add("hash"); + psub_s_exp->add("sha1"); + psub_s_exp->add(checksum, sizeof(checksum)); - if (!add_sub_sexp_to_sexp(s_exp, &sub_s_exp) || - !add_string_block_to_sexp(sub_s_exp, "protected") || - !add_string_block_to_sexp(sub_s_exp, format->g10_type) || - !add_sub_sexp_to_sexp(sub_s_exp, &sub_sub_s_exp) || - !add_sub_sexp_to_sexp(sub_sub_s_exp, &sub_sub_sub_s_exp) || - !add_string_block_to_sexp(sub_sub_sub_s_exp, "sha1") || - !add_block_to_sexp(sub_sub_sub_s_exp, prot->s2k.salt, PGP_SALT_SIZE) || - !add_unsigned_block_to_sexp(sub_sub_sub_s_exp, prot->s2k.iterations) || - !add_block_to_sexp(sub_sub_s_exp, prot->iv, format->iv_size) || - !add_block_to_sexp(sub_s_exp, encrypted_data, encrypted_data_len) || - !add_sub_sexp_to_sexp(s_exp, &sub_s_exp) || - !add_string_block_to_sexp(sub_s_exp, "protected-at") || - !add_block_to_sexp(sub_s_exp, (uint8_t *) protected_at, G10_PROTECTED_AT_SIZE)) { - goto done; + /* write raw secret key to the memory */ + rnp::secure_vector rawkey = raw_s_exp.write_padded(format->cipher_block_size); + + /* derive encrypting key */ + unsigned keysize = pgp_key_size(prot.symm_alg); + if (!keysize) { + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - ret = true; -done: - secure_clear(derived_key, sizeof(derived_key)); - free(encrypted_data); - destroy_s_exp(&raw_s_exp); - dst_close(&raw, true); - botan_cipher_destroy(encrypt); - return ret; + rnp::secure_array derived_key; + if (pgp_s2k_iterated(format->hash_alg, + derived_key.data(), + keysize, + password.c_str(), + prot.s2k.salt, + prot.s2k.iterations)) { + RNP_LOG("s2k key derivation failed"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + + /* encrypt raw key */ + std::unique_ptr enc( + Cipher::encryption(format->cipher, format->cipher_mode, 0, true)); + if (!enc || !enc->set_key(derived_key.data(), keysize) || + !enc->set_iv(prot.iv, format->iv_size)) { + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + + size_t output_written, input_consumed; + std::vector enckey(rawkey.size()); + + if (!enc->finish(enckey.data(), + enckey.size(), + &output_written, + rawkey.data(), + rawkey.size(), + &input_consumed)) { + RNP_LOG("Encryption failed"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + + /* build s_exp with encrypted key */ + psub_s_exp = &add_sub(); + psub_s_exp->add("protected"); + psub_s_exp->add(format->g10_type); + /* protection params: s2k, iv */ + s_exp_t *psub_sub_s_exp = &psub_s_exp->add_sub(); + /* s2k params: hash, salt, iterations */ + s_exp_t *psub_sub_sub_s_exp = &psub_sub_s_exp->add_sub(); + psub_sub_sub_s_exp->add("sha1"); + psub_sub_sub_s_exp->add(prot.s2k.salt, PGP_SALT_SIZE); + psub_sub_sub_s_exp->add(prot.s2k.iterations); + psub_sub_s_exp->add(prot.iv, format->iv_size); + /* encrypted key data itself */ + psub_s_exp->add(enckey.data(), enckey.size()); + /* protected-at */ + psub_s_exp = &add_sub(); + psub_s_exp->add("protected-at"); + psub_s_exp->add((uint8_t *) protected_at, G10_PROTECTED_AT_SIZE); } bool -g10_write_seckey(pgp_dest_t *dst, pgp_key_pkt_t *seckey, const char *password) +g10_write_seckey(pgp_dest_t *dst, pgp_key_pkt_t *seckey, const char *password, rnp::RNG &rng) { - s_exp_t s_exp = {0}; - s_exp_t *sub_s_exp = NULL; - bool is_protected = true; - bool ret = false; + bool is_protected = true; switch (seckey->sec_protection.s2k.usage) { case PGP_S2KU_NONE: @@ -1466,94 +1256,59 @@ break; default: RNP_LOG("unsupported s2k usage"); - goto done; - } - if (!add_string_block_to_sexp(&s_exp, - is_protected ? "protected-private-key" : "private-key") || - !add_sub_sexp_to_sexp(&s_exp, &sub_s_exp) || !write_pubkey(sub_s_exp, seckey)) { - goto done; + return false; } - if (is_protected) { - if (!write_protected_seckey(sub_s_exp, seckey, password)) { - goto done; - } - } else { - if (!write_seckey(sub_s_exp, seckey)) { - goto done; + + try { + s_exp_t s_exp; + s_exp.add(is_protected ? "protected-private-key" : "private-key"); + s_exp_t &pkey = s_exp.add_sub(); + pkey.add_pubkey(*seckey); + + if (is_protected) { + pkey.add_protected_seckey(*seckey, password, rng); + } else { + pkey.add_seckey(*seckey); } + return s_exp.write(*dst) && !dst->werr; + } catch (const std::exception &e) { + RNP_LOG("Failed to write g10 key: %s", e.what()); + return false; } - if (!write_sexp(&s_exp, dst)) { - goto done; - } - ret = !dst->werr; -done: - destroy_s_exp(&s_exp); - return ret; } static bool -g10_calculated_hash(const pgp_key_pkt_t *key, const char *protected_at, uint8_t *checksum) +g10_calculated_hash(const pgp_key_pkt_t &key, const char *protected_at, uint8_t *checksum) { - s_exp_t s_exp = {0}; - s_exp_t * sub_s_exp; pgp_dest_t memdst = {}; - pgp_hash_t hash = {0}; - - if (!pgp_hash_create(&hash, PGP_HASH_SHA1)) { - goto error; - } - - if (hash._output_len != G10_SHA1_HASH_SIZE) { - RNP_LOG( - "wrong hash size %zu, should be %d bytes", hash._output_len, G10_SHA1_HASH_SIZE); - goto error; - } - - if (!write_pubkey(&s_exp, key)) { - RNP_LOG("failed to write pubkey"); - goto error; - } - - if (!write_seckey(&s_exp, key)) { - RNP_LOG("failed to write seckey"); - goto error; - } - - if (!add_sub_sexp_to_sexp(&s_exp, &sub_s_exp)) { - goto error; - } - - if (!add_string_block_to_sexp(sub_s_exp, "protected-at")) { - goto error; - } - - if (!add_block_to_sexp(sub_s_exp, (uint8_t *) protected_at, G10_PROTECTED_AT_SIZE)) { - goto error; - } - - if (init_mem_dest(&memdst, NULL, 0)) { - goto error; - } - - if (!write_sexp(&s_exp, &memdst)) { - goto error; - } - destroy_s_exp(&s_exp); - - RNP_DHEX("data for hashing", (uint8_t *) mem_dest_get_memory(&memdst), memdst.writeb); - - pgp_hash_add(&hash, mem_dest_get_memory(&memdst), memdst.writeb); - dst_close(&memdst, true); - - if (!pgp_hash_finish(&hash, checksum)) { - goto error; + try { + /* populate s_exp */ + s_exp_t s_exp; + s_exp.add_pubkey(key); + s_exp.add_seckey(key); + s_exp_t &s_sub_exp = s_exp.add_sub(); + s_sub_exp.add("protected-at"); + s_sub_exp.add((uint8_t *) protected_at, G10_PROTECTED_AT_SIZE); + /* write it to memdst */ + if (init_mem_dest(&memdst, NULL, 0)) { + return false; + } + mem_dest_secure_memory(&memdst, true); + if (!s_exp.write(memdst)) { + RNP_LOG("Failed to write s_exp"); + dst_close(&memdst, true); + return false; + } + rnp::Hash hash(PGP_HASH_SHA1); + hash.add(mem_dest_get_memory(&memdst), memdst.writeb); + hash.finish(checksum); + dst_close(&memdst, true); + return true; + } catch (const std::exception &e) { + RNP_LOG("Failed to build s_exp: %s", e.what()); + dst_close(&memdst, true); + return false; } - - return true; -error: - dst_close(&memdst, true); - destroy_s_exp(&s_exp); - return false; } bool diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_g10.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_g10.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_g10.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_g10.h 2022-04-15 07:49:22.000000000 +0000 @@ -28,37 +28,15 @@ #define RNP_KEY_STORE_G10_H #include -#include - -#define SXP_MAX_DEPTH 30 - -typedef struct { - size_t len; - uint8_t *bytes; -} s_exp_block_t; - -typedef struct sub_element_t sub_element_t; - -typedef struct { - list sub_elements; // list of sub_element_t -} s_exp_t; - -struct sub_element_t { - bool is_block; - union { - s_exp_t s_exp; - s_exp_block_t block; - }; -}; bool rnp_key_store_g10_from_src(rnp_key_store_t *, pgp_source_t *, const pgp_key_provider_t *); bool rnp_key_store_g10_key_to_dst(pgp_key_t *, pgp_dest_t *); -bool g10_write_seckey(pgp_dest_t *dst, pgp_key_pkt_t *seckey, const char *password); -pgp_key_pkt_t *g10_decrypt_seckey(const uint8_t * data, - size_t data_len, - const pgp_key_pkt_t *pubkey, - const char * password); -bool parse_sexp(s_exp_t *s_exp, const char **r_bytes, size_t *r_length, size_t depth = 1); -void destroy_s_exp(s_exp_t *s_exp); +bool g10_write_seckey(pgp_dest_t * dst, + pgp_key_pkt_t *seckey, + const char * password, + rnp::RNG & rng); +pgp_key_pkt_t *g10_decrypt_seckey(const pgp_rawpacket_t &raw, + const pgp_key_pkt_t & pubkey, + const char * password); #endif // RNP_KEY_STORE_G10_H diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_kbx.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_kbx.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_kbx.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_kbx.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -34,301 +34,292 @@ #include #include #include +#include #include "key_store_pgp.h" #include "key_store_kbx.h" #include "pgp-key.h" #include -#define BLOB_SIZE_LIMIT (5 * 1024 * 1024) // same limit with GnuPG 2.1 +/* same limit with GnuPG 2.1 */ +#define BLOB_SIZE_LIMIT (5 * 1024 * 1024) +/* limit the number of keys/sigs/uids in the blob */ +#define BLOB_OBJ_LIMIT 0x8000 #define BLOB_HEADER_SIZE 0x5 #define BLOB_FIRST_SIZE 0x20 +#define BLOB_KEY_SIZE 0x1C +#define BLOB_UID_SIZE 0x0C +#define BLOB_SIG_SIZE 0x04 +#define BLOB_VALIDITY_SIZE 0x10 -static uint8_t -ru8(uint8_t *p) +uint8_t +kbx_blob_t::ru8(size_t idx) { - return (uint8_t) p[0]; + return image_[idx]; } -static uint16_t -ru16(uint8_t *p) +uint16_t +kbx_blob_t::ru16(size_t idx) { - return (uint16_t)(((uint8_t) p[0] << 8) | (uint8_t) p[1]); + return read_uint16(image_.data() + idx); } -static uint32_t -ru32(uint8_t *p) +uint32_t +kbx_blob_t::ru32(size_t idx) { - return (uint32_t)(((uint8_t) p[0] << 24) | ((uint8_t) p[1] << 16) | ((uint8_t) p[2] << 8) | - (uint8_t) p[3]); + return read_uint32(image_.data() + idx); } -static bool -rnp_key_store_kbx_parse_header_blob(kbx_header_blob_t *first_blob) +kbx_blob_t::kbx_blob_t(std::vector &data) { - uint8_t *image = first_blob->blob.image + BLOB_HEADER_SIZE; + if (data.size() < BLOB_HEADER_SIZE) { + RNP_LOG("Too small KBX blob."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + uint32_t len = read_uint32(data.data()); + if (len > BLOB_SIZE_LIMIT) { + RNP_LOG("Too large KBX blob."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + if (len != data.size()) { + RNP_LOG("KBX blob size mismatch."); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + image_ = data; + type_ = (kbx_blob_type_t) ru8(4); +} - if (first_blob->blob.length != BLOB_FIRST_SIZE) { +bool +kbx_header_blob_t::parse() +{ + if (length() != BLOB_FIRST_SIZE) { RNP_LOG("The first blob has wrong length: %" PRIu32 " but expected %d", - first_blob->blob.length, + length(), (int) BLOB_FIRST_SIZE); return false; } - first_blob->version = ru8(image); - image += 1; - if (first_blob->version != 1) { - RNP_LOG("Wrong version, expect 1 but has %" PRIu8, first_blob->version); + size_t idx = BLOB_HEADER_SIZE; + version_ = ru8(idx++); + if (version_ != 1) { + RNP_LOG("Wrong version, expect 1 but has %" PRIu8, version_); return false; } - first_blob->flags = ru16(image); - image += 2; + flags_ = ru16(idx); + idx += 2; // blob should contains a magic KBXf - if (memcmp(image, "KBXf", 4)) { + if (memcmp(image_.data() + idx, "KBXf", 4)) { RNP_LOG("The first blob hasn't got a KBXf magic string"); return false; } - image += 4; + idx += 4; // RFU - image += 4; + idx += 4; // File creation time - first_blob->file_created_at = ru32(image); - image += 4; + file_created_at_ = ru32(idx); + idx += 4; // Duplicated? - first_blob->file_created_at = ru32(image); - image += 4; + file_created_at_ = ru32(idx); // RFU +4 bytes // RFU +4 bytes return true; } -static bool -rnp_key_store_kbx_parse_pgp_blob(kbx_pgp_blob_t *pgp_blob) +bool +kbx_pgp_blob_t::parse() { - int i; - uint8_t *image = pgp_blob->blob.image; - uint32_t len = pgp_blob->blob.length; - - image += BLOB_HEADER_SIZE; - len -= BLOB_HEADER_SIZE; - - if (len < 15) { + if (image_.size() < 15 + BLOB_HEADER_SIZE) { RNP_LOG("Too few data in the blob."); return false; } - pgp_blob->version = ru8(image); - image++; - - if (pgp_blob->version != 1) { - RNP_LOG("Wrong version: %" PRIu8, pgp_blob->version); - return false; - } - pgp_blob->flags = ru16(image); - image += 2; - - pgp_blob->keyblock_offset = ru32(image); - image += 4; - - pgp_blob->keyblock_length = ru32(image); - image += 4; - - if ((pgp_blob->keyblock_offset > pgp_blob->blob.length) || - (pgp_blob->keyblock_offset > (UINT32_MAX - pgp_blob->keyblock_length)) || - pgp_blob->blob.length < (pgp_blob->keyblock_offset + pgp_blob->keyblock_length)) { - RNP_LOG("Wrong keyblock offset/length, blob size: %" PRIu32 + size_t idx = BLOB_HEADER_SIZE; + /* version */ + version_ = ru8(idx++); + if (version_ != 1) { + RNP_LOG("Wrong version: %" PRIu8, version_); + return false; + } + /* flags */ + flags_ = ru16(idx); + idx += 2; + /* keyblock offset */ + keyblock_offset_ = ru32(idx); + idx += 4; + /* keyblock length */ + keyblock_length_ = ru32(idx); + idx += 4; + + if ((keyblock_offset_ > image_.size()) || + (keyblock_offset_ > (UINT32_MAX - keyblock_length_)) || + (image_.size() < (keyblock_offset_ + keyblock_length_))) { + RNP_LOG("Wrong keyblock offset/length, blob size: %zu" ", keyblock offset: %" PRIu32 ", length: %" PRIu32, - pgp_blob->blob.length, - pgp_blob->keyblock_offset, - pgp_blob->keyblock_length); + image_.size(), + keyblock_offset_, + keyblock_length_); return false; } - - pgp_blob->nkeys = ru16(image); - image += 2; - - if (pgp_blob->nkeys < 1) { + /* number of key blocks */ + size_t nkeys = ru16(idx); + idx += 2; + if (nkeys < 1) { RNP_LOG("PGP blob should contains at least 1 key"); return false; } + if (nkeys > BLOB_OBJ_LIMIT) { + RNP_LOG("Too many keys in the PGP blob"); + return false; + } /* Size of the single key record */ - pgp_blob->keys_len = ru16(image); - image += 2; - - if (pgp_blob->keys_len < 28) { - RNP_LOG("PGP blob needs 28 bytes, but contains: %" PRIu16 " bytes", - pgp_blob->keys_len); + size_t keys_len = ru16(idx); + idx += 2; + if (keys_len < BLOB_KEY_SIZE) { + RNP_LOG( + "PGP blob needs %d bytes, but contains: %zu bytes", (int) BLOB_KEY_SIZE, keys_len); return false; } - len -= 15; - - for (i = 0; i < pgp_blob->nkeys; i++) { - kbx_pgp_key_t nkey = {}; - if (len < pgp_blob->keys_len) { + for (size_t i = 0; i < nkeys; i++) { + if (image_.size() - idx < keys_len) { RNP_LOG("Too few bytes left for key blob"); return false; } - // copy fingerprint - memcpy(nkey.fp, image, 20); - image += 20; - - nkey.keyid_offset = ru32(image); - image += 4; - - nkey.flags = ru16(image); - image += 2; - - // RFU - image += 2; - - // skip padding bytes if it existed - image += pgp_blob->keys_len - 28; - len -= pgp_blob->keys_len; - - if (!list_append(&pgp_blob->keys, &nkey, sizeof(nkey))) { - RNP_LOG("alloc failed"); - return false; - } + kbx_pgp_key_t nkey = {}; + /* copy fingerprint */ + memcpy(nkey.fp, &image_[idx], 20); + idx += 20; + /* keyid offset */ + nkey.keyid_offset = ru32(idx); + idx += 4; + /* flags */ + nkey.flags = ru16(idx); + idx += 2; + /* RFU */ + idx += 2; + /* skip padding bytes if it existed */ + idx += keys_len - BLOB_KEY_SIZE; + keys_.push_back(std::move(nkey)); } - if (len < 2) { + if (image_.size() - idx < 2) { RNP_LOG("No data for sn_size"); return false; } - pgp_blob->sn_size = ru16(image); - image += 2; - len -= 2; + size_t sn_size = ru16(idx); + idx += 2; - if (pgp_blob->sn_size > len) { - RNP_LOG("SN is %" PRIu16 ", while bytes left are %" PRIu32, pgp_blob->sn_size, len); + if (image_.size() - idx < sn_size) { + RNP_LOG("SN is %zu, while bytes left are %zu", sn_size, image_.size() - idx); return false; } - if (pgp_blob->sn_size > 0) { - pgp_blob->sn = (uint8_t *) malloc(pgp_blob->sn_size); - if (pgp_blob->sn == NULL) { - RNP_LOG("bad malloc"); - return false; - } - - memcpy(pgp_blob->sn, image, pgp_blob->sn_size); - image += pgp_blob->sn_size; - len -= pgp_blob->sn_size; + if (sn_size) { + sn_ = {image_.begin() + idx, image_.begin() + idx + sn_size}; + idx += sn_size; } - if (len < 4) { + if (image_.size() - idx < 4) { RNP_LOG("Too few data for uids"); return false; } - pgp_blob->nuids = ru16(image); - image += 2; - pgp_blob->uids_len = ru16(image); - image += 2; - len -= 4; - - if (pgp_blob->uids_len < 12) { - RNP_LOG("Too few bytes for uid struct: %" PRIu16, pgp_blob->uids_len); + size_t nuids = ru16(idx); + if (nuids > BLOB_OBJ_LIMIT) { + RNP_LOG("Too many uids in the PGP blob"); return false; } - for (i = 0; i < pgp_blob->nuids; i++) { - kbx_pgp_uid_t nuid = {}; + size_t uids_len = ru16(idx + 2); + idx += 4; - if (len < pgp_blob->uids_len) { + if (uids_len < BLOB_UID_SIZE) { + RNP_LOG("Too few bytes for uid struct: %zu", uids_len); + return false; + } + + for (size_t i = 0; i < nuids; i++) { + if (image_.size() - idx < uids_len) { RNP_LOG("Too few bytes to read uid struct."); return false; } - nuid.offset = ru32(image); - image += 4; - - nuid.length = ru32(image); - image += 4; - - nuid.flags = ru16(image); - image += 2; - - nuid.validity = ru8(image); - image += 1; - - // RFU - image += 1; - + kbx_pgp_uid_t nuid = {}; + /* offset */ + nuid.offset = ru32(idx); + idx += 4; + /* length */ + nuid.length = ru32(idx); + idx += 4; + /* flags */ + nuid.flags = ru16(idx); + idx += 2; + /* validity */ + nuid.validity = ru8(idx); + idx++; + /* RFU */ + idx++; // skip padding bytes if it existed - image += (pgp_blob->uids_len - 12); - len -= pgp_blob->uids_len; + idx += uids_len - BLOB_UID_SIZE; - if (!list_append(&pgp_blob->uids, &nuid, sizeof(nuid))) { - RNP_LOG("alloc failed"); - return false; - } + uids_.push_back(std::move(nuid)); } - if (len < 4) { + if (image_.size() - idx < 4) { RNP_LOG("No data left for sigs"); return false; } - pgp_blob->nsigs = ru16(image); - image += 2; + size_t nsigs = ru16(idx); + if (nsigs > BLOB_OBJ_LIMIT) { + RNP_LOG("Too many sigs in the PGP blob"); + return false; + } - pgp_blob->sigs_len = ru16(image); - image += 2; - len -= 4; + size_t sigs_len = ru16(idx + 2); + idx += 4; - if (pgp_blob->sigs_len < 4) { - RNP_LOG("Too small SIGN structure: %" PRIu16, pgp_blob->uids_len); + if (sigs_len < BLOB_SIG_SIZE) { + RNP_LOG("Too small SIGN structure: %zu", uids_len); return false; } - for (i = 0; i < pgp_blob->nsigs; i++) { - kbx_pgp_sig_t nsig = {}; - - if (len < pgp_blob->sigs_len) { + for (size_t i = 0; i < nsigs; i++) { + if (image_.size() - idx < sigs_len) { RNP_LOG("Too few data for sig"); return false; } - nsig.expired = ru32(image); - image += 4; + kbx_pgp_sig_t nsig = {}; + nsig.expired = ru32(idx); + idx += 4; // skip padding bytes if it existed - image += (pgp_blob->sigs_len - 4); - len -= pgp_blob->sigs_len; + idx += (sigs_len - BLOB_SIG_SIZE); - if (!list_append(&pgp_blob->sigs, &nsig, sizeof(nsig))) { - RNP_LOG("alloc failed"); - return false; - } + sigs_.push_back(nsig); } - if (len < 16) { + if (image_.size() - idx < BLOB_VALIDITY_SIZE) { RNP_LOG("Too few data for trust/validities"); return false; } - pgp_blob->ownertrust = ru8(image); - image += 1; - - pgp_blob->all_Validity = ru8(image); - image += 1; - + ownertrust_ = ru8(idx); + idx++; + all_validity_ = ru8(idx); + idx++; // RFU - image += 2; - - pgp_blob->recheck_after = ru32(image); - image += 4; - - pgp_blob->latest_timestamp = ru32(image); - image += 4; - - pgp_blob->blob_created_at = ru32(image); - image += 4; + idx += 2; + recheck_after_ = ru32(idx); + idx += 4; + latest_timestamp_ = ru32(idx); + idx += 4; + blob_created_at_ = ru32(idx); + // do not forget to idx += 4 on further expansion // here starts keyblock, UID and reserved space for future usage @@ -339,68 +330,47 @@ return true; } -static kbx_blob_t * -rnp_key_store_kbx_parse_blob(uint8_t *image, uint32_t image_len) +static std::unique_ptr +rnp_key_store_kbx_parse_blob(const uint8_t *image, size_t image_len) { + std::unique_ptr blob; // a blob shouldn't be less of length + type if (image_len < BLOB_HEADER_SIZE) { - RNP_LOG("Blob size is %" PRIu32 " but it shouldn't be less of header", image_len); - return NULL; + RNP_LOG("Blob size is %zu but it shouldn't be less of header", image_len); + return blob; } - uint32_t length = ru32(image + 0); - kbx_blob_type type = (kbx_blob_type) ru8(image + 4); - size_t bloblen = 0; - - switch (type) { - case KBX_EMPTY_BLOB: - bloblen = sizeof(kbx_blob_t); - break; - case KBX_HEADER_BLOB: - bloblen = sizeof(kbx_header_blob_t); - break; - case KBX_PGP_BLOB: - bloblen = sizeof(kbx_pgp_blob_t); - break; - case KBX_X509_BLOB: - // current we doesn't parse X509 blob, so, keep it as is - bloblen = sizeof(kbx_blob_t); - break; - // unsupported blob type - default: - RNP_LOG("Unsupported blob type: %d", (int) type); - return NULL; - } - - kbx_blob_t *blob = (kbx_blob_t *) calloc(1, bloblen); - if (!blob) { - RNP_LOG("Can't allocate memory"); - return NULL; - } - - blob->image = image; - blob->length = length; - blob->type = type; - - // call real parser of blob - switch (type) { - case KBX_HEADER_BLOB: - if (!rnp_key_store_kbx_parse_header_blob((kbx_header_blob_t *) blob)) { - free(blob); - return NULL; + try { + std::vector data(image, image + image_len); + kbx_blob_type_t type = (kbx_blob_type_t) image[4]; + + switch (type) { + case KBX_EMPTY_BLOB: + blob = std::unique_ptr(new kbx_blob_t(data)); + break; + case KBX_HEADER_BLOB: + blob = std::unique_ptr(new kbx_header_blob_t(data)); + break; + case KBX_PGP_BLOB: + blob = std::unique_ptr(new kbx_pgp_blob_t(data)); + break; + case KBX_X509_BLOB: + // current we doesn't parse X509 blob, so, keep it as is + blob = std::unique_ptr(new kbx_blob_t(data)); + break; + // unsupported blob type + default: + RNP_LOG("Unsupported blob type: %d", (int) type); + return blob; } - break; - case KBX_PGP_BLOB: - if (!rnp_key_store_kbx_parse_pgp_blob((kbx_pgp_blob_t *) blob)) { - free_kbx_pgp_blob((kbx_pgp_blob_t *) blob); - free(blob); + + if (!blob->parse()) { return NULL; } - break; - default: - break; + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return NULL; } - return blob; } @@ -409,68 +379,70 @@ pgp_source_t * src, const pgp_key_provider_t *key_provider) { - pgp_source_t memsrc = {}; - size_t has_bytes; - uint8_t * buf; - uint32_t blob_length; - kbx_pgp_blob_t *pgp_blob; - kbx_blob_t ** blob; - bool res = false; - + pgp_source_t memsrc = {}; if (read_mem_src(&memsrc, src)) { RNP_LOG("failed to get data to memory source"); return false; } - has_bytes = memsrc.size; - buf = (uint8_t *) mem_src_get_memory(&memsrc); + size_t has_bytes = memsrc.size; + /* complications below are because of memsrc uses malloc instead of new */ + std::unique_ptr mem( + (uint8_t *) mem_src_get_memory(&memsrc, true), free); + src_close(&memsrc); + uint8_t *buf = mem.get(); + while (has_bytes > 4) { - blob_length = ru32(buf); + size_t blob_length = read_uint32(buf); if (blob_length > BLOB_SIZE_LIMIT) { - RNP_LOG("Blob size is %" PRIu32 " bytes but limit is %d bytes", + RNP_LOG("Blob size is %zu bytes but limit is %d bytes", blob_length, (int) BLOB_SIZE_LIMIT); - goto finish; + return false; + } + if (blob_length < BLOB_HEADER_SIZE) { + RNP_LOG("Too small blob header size"); + return false; } if (has_bytes < blob_length) { - RNP_LOG("Blob have size %" PRIu32 " bytes but file contains only %zu bytes", + RNP_LOG("Blob have size %zu bytes but file contains only %zu bytes", blob_length, has_bytes); - goto finish; + return false; } - blob = (kbx_blob_t **) list_append(&key_store->blobs, NULL, sizeof(*blob)); - if (!blob) { - RNP_LOG("alloc failed"); - goto finish; + auto blob = rnp_key_store_kbx_parse_blob(buf, blob_length); + if (!blob.get()) { + RNP_LOG("Failed to parse blob"); + return false; } - - *blob = rnp_key_store_kbx_parse_blob(buf, blob_length); - if (!*blob) { - list_remove((list_item *) blob); - goto finish; + kbx_blob_t *pblob = blob.get(); + try { + key_store->blobs.push_back(std::move(blob)); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; } - if ((*blob)->type == KBX_PGP_BLOB) { - pgp_source_t blsrc = {}; + if (pblob->type() == KBX_PGP_BLOB) { // parse keyblock if it existed - pgp_blob = (kbx_pgp_blob_t *) *blob; - - if (!pgp_blob->keyblock_length) { + kbx_pgp_blob_t &pgp_blob = dynamic_cast(*pblob); + if (!pgp_blob.keyblock_length()) { RNP_LOG("PGP blob have zero size"); - goto finish; + return false; } + pgp_source_t blsrc = {}; if (init_mem_src(&blsrc, - (*blob)->image + pgp_blob->keyblock_offset, - pgp_blob->keyblock_length, + pgp_blob.image().data() + pgp_blob.keyblock_offset(), + pgp_blob.keyblock_length(), false)) { RNP_LOG("memory src allocation failed"); - goto finish; + return false; } if (rnp_key_store_pgp_read_from_src(key_store, &blsrc)) { src_close(&blsrc); - goto finish; + return false; } src_close(&blsrc); } @@ -479,10 +451,7 @@ buf += blob_length; } - res = true; -finish: - src_close(&memsrc); - return res; + return true; } static bool @@ -518,12 +487,12 @@ static bool rnp_key_store_kbx_write_header(rnp_key_store_t *key_store, pgp_dest_t *dst) { - uint16_t flags = 0; - uint32_t file_created_at = time(NULL); - kbx_blob_t *blob = (kbx_blob_t *) list_front(key_store->blobs); + uint16_t flags = 0; + uint32_t file_created_at = time(NULL); - if (blob && (blob->type == KBX_HEADER_BLOB)) { - file_created_at = ((kbx_header_blob_t *) blob)->file_created_at; + if (!key_store->blobs.empty() && (key_store->blobs[0]->type() == KBX_HEADER_BLOB)) { + kbx_header_blob_t &blob = dynamic_cast(*key_store->blobs[0]); + file_created_at = blob.file_created_at(); } return !(!pu32(dst, BLOB_FIRST_SIZE) || !pu8(dst, KBX_HEADER_BLOB) || @@ -536,16 +505,15 @@ static bool rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest_t *dst) { - unsigned i; - pgp_dest_t memdst = {}; - size_t key_start, uid_start; - uint8_t * p; - uint8_t checksum[20]; - uint32_t pt; - pgp_hash_t hash = {0}; - bool result = false; - list subkey_sig_expirations = NULL; // expirations (uint32_t) of subkey signatures - uint32_t expiration = 0; + unsigned i; + pgp_dest_t memdst = {}; + size_t key_start, uid_start; + uint8_t * p; + uint8_t checksum[20]; + uint32_t pt; + bool result = false; + std::vector subkey_sig_expirations; + uint32_t expiration = 0; if (init_mem_dest(&memdst, NULL, BLOB_SIZE_LIMIT)) { RNP_LOG("alloc failed"); @@ -595,10 +563,12 @@ // load signature expirations while we're at it for (i = 0; i < subkey->sig_count(); i++) { expiration = subkey->get_sig(i).sig.key_expiration(); - if (list_append(&subkey_sig_expirations, &expiration, sizeof(expiration)) == - NULL) { + try { + subkey_sig_expirations.push_back(expiration); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); goto finish; - }; + } } } @@ -629,7 +599,7 @@ } } - if (!pu16(&memdst, key->sig_count() + list_length(subkey_sig_expirations)) || + if (!pu16(&memdst, key->sig_count() + subkey_sig_expirations.size()) || !pu16(&memdst, 4)) { goto finish; } @@ -639,9 +609,7 @@ goto finish; } } - for (list_item *expiration_entry = list_front(subkey_sig_expirations); expiration_entry; - expiration_entry = list_next(expiration_entry)) { - expiration = *(uint32_t *) expiration_entry; + for (auto &expiration : subkey_sig_expirations) { if (!pu32(&memdst, expiration)) { goto finish; } @@ -712,19 +680,13 @@ STORE32BE(p, pt); // checksum - if (!pgp_hash_create(&hash, PGP_HASH_SHA1)) { - RNP_LOG("bad sha1 alloc"); - goto finish; - } - - if (hash._output_len != 20) { - RNP_LOG("wrong hash size %zu, should be 20 bytes", hash._output_len); - goto finish; - } - - pgp_hash_add(&hash, (uint8_t *) mem_dest_get_memory(&memdst), memdst.writeb); - - if (!pgp_hash_finish(&hash, checksum)) { + try { + rnp::Hash hash(PGP_HASH_SHA1); + assert(hash.size() == 20); + hash.add(mem_dest_get_memory(&memdst), memdst.writeb); + hash.finish(checksum); + } catch (const std::exception &e) { + RNP_LOG("Hashing failed: %s", e.what()); goto finish; } @@ -737,24 +699,20 @@ result = dst->werr == RNP_SUCCESS; finish: dst_close(&memdst, true); - list_destroy(&subkey_sig_expirations); return result; } static bool rnp_key_store_kbx_write_x509(rnp_key_store_t *key_store, pgp_dest_t *dst) { - for (list_item *item = list_front(key_store->blobs); item; item = list_next(item)) { - kbx_blob_t *blob = *((kbx_blob_t **) item); - if (blob->type != KBX_X509_BLOB) { + for (auto &blob : key_store->blobs) { + if (blob->type() != KBX_X509_BLOB) { continue; } - - if (!pbuf(dst, blob->image, blob->length)) { + if (!pbuf(dst, blob->image().data(), blob->length())) { return false; } } - return true; } @@ -783,14 +741,3 @@ return true; } - -void -free_kbx_pgp_blob(kbx_pgp_blob_t *pgp_blob) -{ - list_destroy(&pgp_blob->keys); - if (pgp_blob->sn_size > 0) { - free(pgp_blob->sn); - } - list_destroy(&pgp_blob->uids); - list_destroy(&pgp_blob->sigs); -} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_kbx.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_kbx.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/key_store_kbx.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/key_store_kbx.h 2022-04-15 07:49:22.000000000 +0000 @@ -28,9 +28,9 @@ #define RNP_KEY_STORE_KBX_H #include +#include "sec_profile.hpp" bool rnp_key_store_kbx_from_src(rnp_key_store_t *, pgp_source_t *, const pgp_key_provider_t *); bool rnp_key_store_kbx_to_dst(rnp_key_store_t *, pgp_dest_t *); -void free_kbx_pgp_blob(kbx_pgp_blob_t *); #endif // RNP_KEY_STORE_KBX_H diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/rnp_key_store.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/rnp_key_store.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librekey/rnp_key_store.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librekey/rnp_key_store.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -53,6 +53,7 @@ #include "key_store_pgp.h" #include "key_store_kbx.h" #include "key_store_g10.h" +#include "kbx_blob.hpp" #include "pgp-key.h" #include "fingerprint.h" @@ -82,7 +83,6 @@ errno = 0; while (!((dirname = rnp_readdir_name(dir)).empty())) { std::string path = key_store->path + '/' + dirname; - RNP_DLOG("Loading G10 key from file '%s'", path.c_str()); if (init_file_src(&src, path.c_str())) { RNP_LOG("failed to read file %s", path.c_str()); @@ -137,7 +137,6 @@ /* write g10 key store to the directory */ if (key_store->format == PGP_KEY_STORE_G10) { char path[MAXPATHLEN]; - char grips[PGP_FINGERPRINT_HEX_SIZE]; struct stat path_stat; if (rnp_stat(key_store->path.c_str(), &path_stat) != -1) { @@ -157,11 +156,9 @@ } for (auto &key : key_store->keys) { - snprintf(path, - sizeof(path), - "%s/%s.key", - key_store->path.c_str(), - rnp_strhexdump_upper(grips, key.grip().data(), key.grip().size(), "")); + char grip[PGP_FINGERPRINT_HEX_SIZE] = {0}; + rnp::hex_encode(key.grip().data(), key.grip().size(), grip, sizeof(grip)); + snprintf(path, sizeof(path), "%s/%s.key", key_store->path.c_str(), grip); if (init_tmpfile_dest(&keydst, path, true)) { RNP_LOG("failed to create file"); @@ -222,15 +219,7 @@ { keyring->keybyfp.clear(); keyring->keys.clear(); - for (list_item *item = list_front(keyring->blobs); item; item = list_next(item)) { - kbx_blob_t *blob = *((kbx_blob_t **) item); - if (blob->type == KBX_PGP_BLOB) { - kbx_pgp_blob_t *pgpblob = (kbx_pgp_blob_t *) blob; - free_kbx_pgp_blob(pgpblob); - } - free(blob); - } - list_destroy(&keyring->blobs); + keyring->blobs.clear(); } size_t @@ -332,12 +321,11 @@ } } - RNP_DLOG("keyc %lu", (long unsigned) rnp_key_store_get_key_count(keyring)); /* validate all added keys if not disabled */ if (!keyring->disable_validation && !oldkey->validated()) { - oldkey->validate_subkey(primary); + oldkey->validate_subkey(primary, keyring->secctx); } - if (!oldkey->refresh_data(primary)) { + if (!oldkey->refresh_data(primary, keyring->secctx)) { RNP_LOG_KEY("Failed to refresh subkey %s data", srckey); RNP_LOG_KEY("primary key is %s", primary); } @@ -385,11 +373,10 @@ } } - RNP_DLOG("keyc %lu", (long unsigned) rnp_key_store_get_key_count(keyring)); /* validate all added keys if not disabled or already validated */ if (!keyring->disable_validation && !added_key->validated()) { added_key->revalidate(*keyring); - } else if (!added_key->refresh_data()) { + } else if (!added_key->refresh_data(keyring->secctx)) { RNP_LOG_KEY("Failed to refresh key %s data", srckey); } return added_key; @@ -404,32 +391,31 @@ /* add public key */ pgp_key_t *exkey = rnp_key_store_get_key_by_fpr(keyring, srckey->fp()); size_t expackets = exkey ? exkey->rawpkt_count() : 0; - keyring->disable_validation = true; try { pgp_key_t keycp(*srckey, pubkey); + keyring->disable_validation = true; exkey = rnp_key_store_add_key(keyring, &keycp); + keyring->disable_validation = false; + if (!exkey) { + RNP_LOG("failed to add key to the keyring"); + return NULL; + } + bool changed = exkey->rawpkt_count() > expackets; + if (changed || !exkey->validated()) { + /* this will revalidated primary key with all subkeys */ + exkey->revalidate(*keyring); + } + if (status) { + *status = changed ? (expackets ? PGP_KEY_IMPORT_STATUS_UPDATED : + PGP_KEY_IMPORT_STATUS_NEW) : + PGP_KEY_IMPORT_STATUS_UNCHANGED; + } + return exkey; } catch (const std::exception &e) { RNP_LOG("%s", e.what()); keyring->disable_validation = false; return NULL; } - keyring->disable_validation = false; - if (!exkey) { - RNP_LOG("failed to add key to the keyring"); - return NULL; - } - bool changed = exkey->rawpkt_count() > expackets; - if (changed || !exkey->validated()) { - /* this will revalidated primary key with all subkeys */ - exkey->revalidate(*keyring); - } - if (status) { - *status = changed ? - (expackets ? PGP_KEY_IMPORT_STATUS_UPDATED : PGP_KEY_IMPORT_STATUS_NEW) : - PGP_KEY_IMPORT_STATUS_UNCHANGED; - } - - return exkey; } pgp_key_t * @@ -445,6 +431,7 @@ // fall back to key id search if (sig->has_keyid()) { search.by.keyid = sig->keyid(); + search.type = PGP_KEY_SEARCH_KEYID; return rnp_key_store_search(store, &search, NULL); } return NULL; @@ -471,7 +458,7 @@ try { pgp_key_t tmpkey(key->pkt()); tmpkey.add_sig(*sig); - if (!tmpkey.refresh_data(primary)) { + if (!tmpkey.refresh_data(primary, keyring->secctx)) { RNP_LOG("Failed to add signature to the key."); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } @@ -506,7 +493,7 @@ try { pgp_key_t tmpkey(key->pkt()); tmpkey.add_sig(*sig); - if (!tmpkey.refresh_data()) { + if (!tmpkey.refresh_data(keyring->secctx)) { RNP_LOG("Failed to add signature to the key."); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } @@ -586,67 +573,6 @@ return true; } -/** - \ingroup HighLevel_KeyringFind - - \brief Finds key in keyring from its Key ID - - \param keyring Keyring to be searched - \param keyid ID of required key - - \return Pointer to key, if found; NULL, if not found - - \note This returns a pointer to the key inside the given keyring, - not a copy. Do not free it after use. - -*/ -pgp_key_t * -rnp_key_store_get_key_by_id(rnp_key_store_t * keyring, - const pgp_key_id_t &keyid, - pgp_key_t * after) -{ - RNP_DLOG("searching keyring %p", keyring); - if (!keyring) { - return NULL; - } - - auto it = - std::find_if(keyring->keys.begin(), keyring->keys.end(), [after](const pgp_key_t &key) { - return !after || (after == &key); - }); - if (after && (it == keyring->keys.end())) { - RNP_LOG("searching with non-keyrings after param"); - return NULL; - } - if (after) { - it = std::next(it); - } - it = std::find_if(it, keyring->keys.end(), [keyid](const pgp_key_t &key) { - return (key.keyid() == keyid) || !memcmp(key.keyid().data() + PGP_KEY_ID_SIZE / 2, - keyid.data(), - PGP_KEY_ID_SIZE / 2); - }); - return (it == keyring->keys.end()) ? NULL : &(*it); -} - -const pgp_key_t * -rnp_key_store_get_key_by_grip(const rnp_key_store_t *keyring, const pgp_key_grip_t &grip) -{ - auto it = std::find_if(keyring->keys.begin(), - keyring->keys.end(), - [grip](const pgp_key_t &key) { return key.grip() == grip; }); - return (it == keyring->keys.end()) ? NULL : &(*it); -} - -pgp_key_t * -rnp_key_store_get_key_by_grip(rnp_key_store_t *keyring, const pgp_key_grip_t &grip) -{ - auto it = std::find_if(keyring->keys.begin(), - keyring->keys.end(), - [grip](const pgp_key_t &key) { return key.grip() == grip; }); - return (it == keyring->keys.end()) ? NULL : &(*it); -} - const pgp_key_t * rnp_key_store_get_key_by_fpr(const rnp_key_store_t *keyring, const pgp_fingerprint_t &fpr) { @@ -675,7 +601,8 @@ } if (subkey->has_primary_fp()) { - return rnp_key_store_get_key_by_fpr(keyring, subkey->primary_fp()); + pgp_key_t *primary = rnp_key_store_get_key_by_fpr(keyring, subkey->primary_fp()); + return primary && primary->is_primary() ? primary : NULL; } for (size_t i = 0; i < subkey->sig_count(); i++) { @@ -684,166 +611,145 @@ continue; } - if (subsig.sig.has_keyfp()) { - return rnp_key_store_get_key_by_fpr(keyring, subsig.sig.keyfp()); - } - - if (subsig.sig.has_keyid()) { - return rnp_key_store_get_key_by_id(keyring, subsig.sig.keyid(), NULL); + pgp_key_t *primary = rnp_key_store_get_signer_key(keyring, &subsig.sig); + if (primary && primary->is_primary()) { + return primary; } } - return NULL; } -static bool -grip_hash_mpi(pgp_hash_t *hash, const pgp_mpi_t *val, const char name, bool lzero) +static void +grip_hash_mpi(rnp::Hash &hash, const pgp_mpi_t &val, const char name, bool lzero = true) { - size_t len; - size_t idx; - char buf[20] = {0}; - - len = mpi_bytes(val); - for (idx = 0; (idx < len) && (val->mpi[idx] == 0); idx++) + size_t len = mpi_bytes(&val); + size_t idx = 0; + for (idx = 0; (idx < len) && !val.mpi[idx]; idx++) ; if (name) { size_t hlen = idx >= len ? 0 : len - idx; - if ((len > idx) && lzero && (val->mpi[idx] & 0x80)) { + if ((len > idx) && lzero && (val.mpi[idx] & 0x80)) { hlen++; } + char buf[20] = {0}; snprintf(buf, sizeof(buf), "(1:%c%zu:", name, hlen); - pgp_hash_add(hash, buf, strlen(buf)); + hash.add(buf, strlen(buf)); } if (idx < len) { - /* gcrypt prepends mpis with zero if hihger bit is set */ - if (lzero && (val->mpi[idx] & 0x80)) { - buf[0] = '\0'; - pgp_hash_add(hash, buf, 1); + /* gcrypt prepends mpis with zero if higher bit is set */ + if (lzero && (val.mpi[idx] & 0x80)) { + uint8_t zero = 0; + hash.add(&zero, 1); } - pgp_hash_add(hash, val->mpi + idx, len - idx); + hash.add(val.mpi + idx, len - idx); } - if (name) { - pgp_hash_add(hash, ")", 1); + hash.add(")", 1); } - - return true; } -static bool -grip_hash_ecc_hex(pgp_hash_t *hash, const char *hex, char name) +static void +grip_hash_ecc_hex(rnp::Hash &hash, const char *hex, char name) { pgp_mpi_t mpi = {}; mpi.len = rnp::hex_decode(hex, mpi.mpi, sizeof(mpi.mpi)); if (!mpi.len) { RNP_LOG("wrong hex mpi"); - return false; + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } /* libgcrypt doesn't add leading zero when hashes ecc mpis */ - return grip_hash_mpi(hash, &mpi, name, false); + return grip_hash_mpi(hash, mpi, name, false); } -static bool -grip_hash_ec(pgp_hash_t *hash, const pgp_ec_key_t *key) +static void +grip_hash_ec(rnp::Hash &hash, const pgp_ec_key_t &key) { - const ec_curve_desc_t *desc = get_curve_desc(key->curve); - pgp_mpi_t g = {}; - size_t len = 0; - bool res = false; - + const ec_curve_desc_t *desc = get_curve_desc(key.curve); if (!desc) { - RNP_LOG("unknown curve %d", (int) key->curve); - return false; + RNP_LOG("unknown curve %d", (int) key.curve); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } /* build uncompressed point from gx and gy */ + pgp_mpi_t g = {}; g.mpi[0] = 0x04; g.len = 1; - len = rnp::hex_decode(desc->gx, g.mpi + g.len, sizeof(g.mpi) - g.len); + size_t len = rnp::hex_decode(desc->gx, g.mpi + g.len, sizeof(g.mpi) - g.len); if (!len) { RNP_LOG("wrong x mpi"); - return false; + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } g.len += len; len = rnp::hex_decode(desc->gy, g.mpi + g.len, sizeof(g.mpi) - g.len); if (!len) { RNP_LOG("wrong y mpi"); - return false; + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } g.len += len; /* p, a, b, g, n, q */ - res = grip_hash_ecc_hex(hash, desc->p, 'p') && grip_hash_ecc_hex(hash, desc->a, 'a') && - grip_hash_ecc_hex(hash, desc->b, 'b') && grip_hash_mpi(hash, &g, 'g', false) && - grip_hash_ecc_hex(hash, desc->n, 'n'); + grip_hash_ecc_hex(hash, desc->p, 'p'); + grip_hash_ecc_hex(hash, desc->a, 'a'); + grip_hash_ecc_hex(hash, desc->b, 'b'); + grip_hash_mpi(hash, g, 'g', false); + grip_hash_ecc_hex(hash, desc->n, 'n'); - if ((key->curve == PGP_CURVE_ED25519) || (key->curve == PGP_CURVE_25519)) { + if ((key.curve == PGP_CURVE_ED25519) || (key.curve == PGP_CURVE_25519)) { if (g.len < 1) { RNP_LOG("wrong 25519 p"); - return false; + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - g.len = key->p.len - 1; - memcpy(g.mpi, key->p.mpi + 1, g.len); - res &= grip_hash_mpi(hash, &g, 'q', false); + g.len = key.p.len - 1; + memcpy(g.mpi, key.p.mpi + 1, g.len); + grip_hash_mpi(hash, g, 'q', false); } else { - res &= grip_hash_mpi(hash, &key->p, 'q', false); + grip_hash_mpi(hash, key.p, 'q', false); } - return res; } /* keygrip is subjectKeyHash from pkcs#15 for RSA. */ bool rnp_key_store_get_key_grip(const pgp_key_material_t *key, pgp_key_grip_t &grip) { - pgp_hash_t hash = {0}; - - if (!pgp_hash_create(&hash, PGP_HASH_SHA1)) { - RNP_LOG("bad sha1 alloc"); - return false; - } - - switch (key->alg) { - case PGP_PKA_RSA: - case PGP_PKA_RSA_SIGN_ONLY: - case PGP_PKA_RSA_ENCRYPT_ONLY: - grip_hash_mpi(&hash, &key->rsa.n, '\0', true); - break; - - case PGP_PKA_DSA: - grip_hash_mpi(&hash, &key->dsa.p, 'p', true); - grip_hash_mpi(&hash, &key->dsa.q, 'q', true); - grip_hash_mpi(&hash, &key->dsa.g, 'g', true); - grip_hash_mpi(&hash, &key->dsa.y, 'y', true); - break; - - case PGP_PKA_ELGAMAL: - case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - grip_hash_mpi(&hash, &key->eg.p, 'p', true); - grip_hash_mpi(&hash, &key->eg.g, 'g', true); - grip_hash_mpi(&hash, &key->eg.y, 'y', true); - break; - - case PGP_PKA_ECDH: - case PGP_PKA_ECDSA: - case PGP_PKA_EDDSA: - case PGP_PKA_SM2: - if (!grip_hash_ec(&hash, &key->ec)) { - pgp_hash_finish(&hash, grip.data()); + try { + rnp::Hash hash(PGP_HASH_SHA1); + switch (key->alg) { + case PGP_PKA_RSA: + case PGP_PKA_RSA_SIGN_ONLY: + case PGP_PKA_RSA_ENCRYPT_ONLY: + grip_hash_mpi(hash, key->rsa.n, '\0'); + break; + case PGP_PKA_DSA: + grip_hash_mpi(hash, key->dsa.p, 'p'); + grip_hash_mpi(hash, key->dsa.q, 'q'); + grip_hash_mpi(hash, key->dsa.g, 'g'); + grip_hash_mpi(hash, key->dsa.y, 'y'); + break; + case PGP_PKA_ELGAMAL: + case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: + grip_hash_mpi(hash, key->eg.p, 'p'); + grip_hash_mpi(hash, key->eg.g, 'g'); + grip_hash_mpi(hash, key->eg.y, 'y'); + break; + case PGP_PKA_ECDH: + case PGP_PKA_ECDSA: + case PGP_PKA_EDDSA: + case PGP_PKA_SM2: + grip_hash_ec(hash, key->ec); + break; + default: + RNP_LOG("unsupported public-key algorithm %d", (int) key->alg); return false; } - break; - - default: - RNP_LOG("unsupported public-key algorithm %d", (int) key->alg); - pgp_hash_finish(&hash, grip.data()); + return hash.finish(grip.data()) == grip.size(); + } catch (const std::exception &e) { + RNP_LOG("Grip calculation failed: %s", e.what()); return false; } - - return pgp_hash_finish(&hash, grip.data()) == grip.size(); } pgp_key_t * @@ -880,7 +786,10 @@ return (it == keyring->keys.end()) ? NULL : &(*it); } -rnp_key_store_t::rnp_key_store_t(pgp_key_store_format_t _format, const std::string &_path) +rnp_key_store_t::rnp_key_store_t(pgp_key_store_format_t _format, + const std::string & _path, + rnp::SecurityContext & ctx) + : secctx(ctx) { if (_format == PGP_KEY_STORE_UNKNOWN) { RNP_LOG("Invalid key store format"); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-armor.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-armor.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-armor.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-armor.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -64,7 +64,7 @@ bool eofb64; /* end of base64 stream reached */ uint8_t readcrc[3]; /* crc-24 from the armored data */ bool has_crc; /* message contains CRC line */ - pgp_hash_t crc_ctx; /* CTX used to calculate CRC */ + rnp::CRC24 crc_ctx; /* CTX used to calculate CRC */ } pgp_source_armored_param_t; typedef struct pgp_dest_armored_param_t { @@ -75,7 +75,7 @@ unsigned llen; /* length of the base64 line, defaults to 76 as per RFC */ uint8_t tail[2]; /* bytes which didn't fit into 3-byte boundary */ unsigned tailc; /* number of bytes in tail */ - pgp_hash_t crc_ctx; /* CTX used to calculate CRC */ + rnp::CRC24 crc_ctx; /* CTX used to calculate CRC */ } pgp_dest_armored_param_t; /* @@ -249,7 +249,12 @@ if (param->restlen - param->restpos >= len) { memcpy(bufptr, ¶m->rest[param->restpos], len); param->restpos += len; - pgp_hash_add(¶m->crc_ctx, bufptr, len); + try { + param->crc_ctx.add(bufptr, len); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; + } *readres = len; return true; } else { @@ -363,7 +368,12 @@ *bptr++ = b24 & 0xff; } - pgp_hash_add(¶m->crc_ctx, buf, bufptr - (uint8_t *) buf); + try { + param->crc_ctx.add(buf, bufptr - (uint8_t *) buf); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; + } if (param->eofb64) { if ((dend - dptr + eqcount) % 4 != 0) { @@ -381,9 +391,11 @@ uint8_t crc_fin[5]; /* Calculate CRC after reading whole input stream */ - pgp_hash_add(¶m->crc_ctx, param->rest, bptr - param->rest); - if (!pgp_hash_finish(¶m->crc_ctx, crc_fin)) { - RNP_LOG("Can't finalize RNP ctx"); + try { + param->crc_ctx.add(param->rest, bptr - param->rest); + param->crc_ctx.finish(crc_fin); + } catch (const std::exception &e) { + RNP_LOG("Can't finalize RNP ctx: %s", e.what()); return false; } @@ -405,7 +417,12 @@ read = left > param->restlen ? param->restlen : left; memcpy(bufptr, param->rest, read); if (!param->eofb64) { - pgp_hash_add(¶m->crc_ctx, bufptr, read); + try { + param->crc_ctx.add(bufptr, read); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; + } } left -= read; param->restpos += read; @@ -421,13 +438,12 @@ pgp_source_armored_param_t *param = (pgp_source_armored_param_t *) src->param; if (param) { - (void) pgp_hash_finish(¶m->crc_ctx, NULL); free(param->armorhdr); free(param->version); free(param->comment); free(param->hash); free(param->charset); - free(param); + delete param; src->param = NULL; } } @@ -661,7 +677,7 @@ header[hdrlen] = '\0'; } else if (hdrlen) { src_skip(param->readsrc, hdrlen); - if (rnp_is_blank_line(header, hdrlen)) { + if (rnp::is_blank_line(header, hdrlen)) { return src_skip_eol(param->readsrc); } } else { @@ -708,18 +724,18 @@ rnp_result_t errcode = RNP_ERROR_GENERIC; pgp_source_armored_param_t *param; - if (!init_src_common(src, sizeof(*param))) { + if (!init_src_common(src, 0)) { return RNP_ERROR_OUT_OF_MEMORY; } - - param = (pgp_source_armored_param_t *) src->param; - param->readsrc = readsrc; - - if (!pgp_hash_create_crc24(¶m->crc_ctx)) { - RNP_LOG("Internal error"); - return RNP_ERROR_GENERIC; + try { + param = new pgp_source_armored_param_t(); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_OUT_OF_MEMORY; } + param->readsrc = readsrc; + src->param = param; src->read = armored_src_read; src->close = armored_src_close; src->type = PGP_STREAM_ARMORED; @@ -844,7 +860,12 @@ } /* update crc */ - pgp_hash_add(¶m->crc_ctx, buf, len); + try { + param->crc_ctx.add(buf, len); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_BAD_STATE; + } /* processing tail if any */ if (len + param->tailc < 3) { @@ -953,7 +974,11 @@ buf[0] = CH_EQ; // At this point crc_ctx is initialized, so call can't fail - (void) pgp_hash_finish(¶m->crc_ctx, crcbuf); + try { + param->crc_ctx.finish(crcbuf); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + } armored_encode3(&buf[1], crcbuf); dst_write(param->writedst, buf, 5); armor_write_eol(param); @@ -974,10 +999,8 @@ if (!param) { return; } - /* dst_close may be called without dst_finish on error */ - (void) pgp_hash_finish(¶m->crc_ctx, NULL); - free(param); + delete param; dst->param = NULL; } @@ -988,10 +1011,17 @@ pgp_dest_armored_param_t *param; rnp_result_t ret = RNP_SUCCESS; - if (!init_dst_common(dst, sizeof(*param))) { + if (!init_dst_common(dst, 0)) { + return RNP_ERROR_OUT_OF_MEMORY; + } + try { + param = new pgp_dest_armored_param_t(); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); return RNP_ERROR_OUT_OF_MEMORY; } - param = (pgp_dest_armored_param_t *) dst->param; + + dst->param = param; dst->write = armored_dst_write; dst->finish = armored_dst_finish; dst->close = armored_dst_close; @@ -999,11 +1029,6 @@ dst->writeb = 0; dst->clen = 0; - if (!pgp_hash_create_crc24(¶m->crc_ctx)) { - RNP_LOG("Internal error"); - return RNP_ERROR_GENERIC; - } - param->writedst = writedst; param->type = msgtype; param->usecrlf = true; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-common.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-common.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-common.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-common.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -47,7 +47,9 @@ #include "stream-common.h" #include "types.h" #include "file-utils.h" +#include "crypto/mem.h" #include +#include bool src_read(pgp_source_t *src, void *buf, size_t len, size_t *readres) @@ -486,6 +488,7 @@ void * memory; bool free; bool discard_overflow; + bool secure; } pgp_dest_mem_param_t; static bool @@ -601,10 +604,8 @@ } const void * -mem_src_get_memory(pgp_source_t *src) +mem_src_get_memory(pgp_source_t *src, bool own) { - pgp_source_mem_param_t *param; - if (src->type != PGP_STREAM_MEMORY) { RNP_LOG("wrong function call"); return NULL; @@ -614,7 +615,10 @@ return NULL; } - param = (pgp_source_mem_param_t *) src->param; + pgp_source_mem_param_t *param = (pgp_source_mem_param_t *) src->param; + if (own) { + param->free = false; + } return param->memory; } @@ -722,16 +726,15 @@ } typedef struct pgp_dest_file_param_t { - int fd; - int errcode; - bool overwrite; - char path[PATH_MAX]; + int fd; + int errcode; + bool overwrite; + std::string path; } pgp_dest_file_param_t; static rnp_result_t file_dst_write(pgp_dest_t *dst, const void *buf, size_t len) { - ssize_t ret; pgp_dest_file_param_t *param = (pgp_dest_file_param_t *) dst->param; if (!param) { @@ -740,7 +743,7 @@ } /* we assyme that blocking I/O is used so everything is written or error received */ - ret = write(param->fd, buf, len); + ssize_t ret = write(param->fd, buf, len); if (ret < 0) { param->errcode = errno; RNP_LOG("write failed, error %d", param->errcode); @@ -755,7 +758,6 @@ file_dst_close(pgp_dest_t *dst, bool discard) { pgp_dest_file_param_t *param = (pgp_dest_file_param_t *) dst->param; - if (!param) { return; } @@ -763,52 +765,42 @@ if (dst->type == PGP_STREAM_FILE) { close(param->fd); if (discard) { - rnp_unlink(param->path); + rnp_unlink(param->path.c_str()); } } - free(param); + delete param; dst->param = NULL; } static rnp_result_t init_fd_dest(pgp_dest_t *dst, int fd, const char *path) { - pgp_dest_file_param_t *param; - size_t path_len = strlen(path); - if (path_len >= sizeof(param->path)) { - RNP_LOG("path too long"); - return RNP_ERROR_BAD_PARAMETERS; + if (!init_dst_common(dst, 0)) { + return RNP_ERROR_OUT_OF_MEMORY; } - if (!init_dst_common(dst, sizeof(*param))) { + + try { + std::unique_ptr param(new pgp_dest_file_param_t()); + param->path = path; + param->fd = fd; + dst->param = param.release(); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); return RNP_ERROR_OUT_OF_MEMORY; } - param = (pgp_dest_file_param_t *) dst->param; - param->fd = fd; - memcpy(param->path, path, path_len + 1); dst->write = file_dst_write; dst->close = file_dst_close; dst->type = PGP_STREAM_FILE; - return RNP_SUCCESS; } rnp_result_t init_file_dest(pgp_dest_t *dst, const char *path, bool overwrite) { - int fd; - int flags; - struct stat st; - pgp_dest_file_param_t *param; - - size_t path_len = strlen(path); - if (path_len >= sizeof(param->path)) { - RNP_LOG("path too long"); - return RNP_ERROR_BAD_PARAMETERS; - } - /* check whether file/dir already exists */ + struct stat st; if (!rnp_stat(path, &st)) { if (!overwrite) { RNP_LOG("file already exists: '%s'", path); @@ -824,7 +816,7 @@ } } - flags = O_WRONLY | O_CREAT; + int flags = O_WRONLY | O_CREAT; flags |= overwrite ? O_TRUNC : O_EXCL; #ifdef HAVE_O_BINARY flags |= O_BINARY; @@ -833,8 +825,7 @@ flags |= _O_BINARY; #endif #endif - fd = rnp_open(path, flags, S_IRUSR | S_IWUSR); - + int fd = rnp_open(path, flags, S_IRUSR | S_IWUSR); if (fd < 0) { RNP_LOG("failed to create file '%s'. Error %d.", path, errno); return RNP_ERROR_WRITE; @@ -853,58 +844,57 @@ file_tmpdst_finish(pgp_dest_t *dst) { pgp_dest_file_param_t *param = (pgp_dest_file_param_t *) dst->param; - size_t plen = 0; - struct stat st; - char origpath[PATH_MAX] = {0}; - if (!param) { return RNP_ERROR_BAD_PARAMETERS; } - /* remove suffix so we have required path */ - plen = strnlen(param->path, sizeof(param->path)); - if (plen < strlen(TMPDST_SUFFIX)) { - return RNP_ERROR_BAD_PARAMETERS; - } - strncpy(origpath, param->path, plen - strlen(TMPDST_SUFFIX)); - - /* rename the temporary file */ + /* close the file */ close(param->fd); param->fd = -1; - /* check if file already exists */ - if (!rnp_stat(origpath, &st)) { - if (!param->overwrite) { - RNP_LOG("target path already exists"); - return RNP_ERROR_BAD_STATE; - } + /* rename the temporary file */ + if (param->path.size() < strlen(TMPDST_SUFFIX)) { + return RNP_ERROR_BAD_PARAMETERS; + } + try { + /* remove suffix so we have required path */ + std::string origpath(param->path.begin(), param->path.end() - strlen(TMPDST_SUFFIX)); + /* check if file already exists */ + struct stat st; + if (!rnp_stat(origpath.c_str(), &st)) { + if (!param->overwrite) { + RNP_LOG("target path already exists"); + return RNP_ERROR_BAD_STATE; + } #ifdef _WIN32 - /* rename() call on Windows fails if destination exists */ - else { - rnp_unlink(origpath); - } + /* rename() call on Windows fails if destination exists */ + else { + rnp_unlink(origpath.c_str()); + } #endif - /* we should remove dir if overwriting, file will be unlinked in rename call */ - if (S_ISDIR(st.st_mode) && rmdir(origpath)) { - RNP_LOG("failed to remove directory"); - return RNP_ERROR_BAD_STATE; + /* we should remove dir if overwriting, file will be unlinked in rename call */ + if (S_ISDIR(st.st_mode) && rmdir(origpath.c_str())) { + RNP_LOG("failed to remove directory"); + return RNP_ERROR_BAD_STATE; + } } - } - if (rnp_rename(param->path, origpath)) { - RNP_LOG("failed to rename temporary path to target file: %s", strerror(errno)); + if (rnp_rename(param->path.c_str(), origpath.c_str())) { + RNP_LOG("failed to rename temporary path to target file: %s", strerror(errno)); + return RNP_ERROR_BAD_STATE; + } + return RNP_SUCCESS; + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); return RNP_ERROR_BAD_STATE; } - - return RNP_SUCCESS; } static void file_tmpdst_close(pgp_dest_t *dst, bool discard) { pgp_dest_file_param_t *param = (pgp_dest_file_param_t *) dst->param; - if (!param) { return; } @@ -913,43 +903,44 @@ if (!dst->finished && (dst->type == PGP_STREAM_FILE)) { close(param->fd); if (discard) { - rnp_unlink(param->path); + rnp_unlink(param->path.c_str()); } } - free(param); + delete param; dst->param = NULL; } rnp_result_t init_tmpfile_dest(pgp_dest_t *dst, const char *path, bool overwrite) { - char tmp[PATH_MAX]; - pgp_dest_file_param_t *param = NULL; - rnp_result_t res = RNP_ERROR_GENERIC; - int ires = 0; - - ires = snprintf(tmp, sizeof(tmp), "%s%s", path, TMPDST_SUFFIX); - if ((ires < 0) || ((size_t) ires >= sizeof(tmp))) { - RNP_LOG("failed to build file path"); - return RNP_ERROR_BAD_PARAMETERS; - } + try { + std::string tmp = std::string(path) + std::string(TMPDST_SUFFIX); + /* make sure tmp.data() is zero-terminated */ + tmp.push_back('\0'); #if defined(HAVE_MKSTEMP) && !defined(_WIN32) - int fd = mkstemp(tmp); + int fd = mkstemp(&tmp[0]); #else - int fd = rnp_mkstemp(tmp); + int fd = rnp_mkstemp(&tmp[0]); #endif - if (fd < 0) { - RNP_LOG("failed to create temporary file with template '%s'. Error %d.", tmp, errno); - return RNP_ERROR_WRITE; - } - if ((res = init_fd_dest(dst, fd, tmp))) { - close(fd); - return res; + if (fd < 0) { + RNP_LOG("failed to create temporary file with template '%s'. Error %d.", + tmp.c_str(), + errno); + return RNP_ERROR_WRITE; + } + rnp_result_t res = init_fd_dest(dst, fd, tmp.c_str()); + if (res) { + close(fd); + return res; + } + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_BAD_STATE; } /* now let's change some parameters to handle temporary file correctly */ - param = (pgp_dest_file_param_t *) dst->param; + pgp_dest_file_param_t *param = (pgp_dest_file_param_t *) dst->param; param->overwrite = overwrite; dst->finish = file_tmpdst_finish; dst->close = file_tmpdst_close; @@ -959,28 +950,18 @@ rnp_result_t init_stdout_dest(pgp_dest_t *dst) { - pgp_dest_file_param_t *param; - - if (!init_dst_common(dst, sizeof(*param))) { - return RNP_ERROR_OUT_OF_MEMORY; + rnp_result_t res = init_fd_dest(dst, STDOUT_FILENO, ""); + if (res) { + return res; } - - param = (pgp_dest_file_param_t *) dst->param; - param->fd = STDOUT_FILENO; - dst->write = file_dst_write; - dst->close = file_dst_close; dst->type = PGP_STREAM_STDOUT; - return RNP_SUCCESS; } static rnp_result_t mem_dst_write(pgp_dest_t *dst, const void *buf, size_t len) { - size_t alloc; - void * newalloc; pgp_dest_mem_param_t *param = (pgp_dest_mem_param_t *) dst->param; - if (!param) { return RNP_ERROR_BAD_PARAMETERS; } @@ -1000,15 +981,20 @@ } /* round up to the page boundary and do it exponentially */ - alloc = ((dst->writeb + len) * 2 + 4095) / 4096 * 4096; + size_t alloc = ((dst->writeb + len) * 2 + 4095) / 4096 * 4096; if ((param->maxalloc > 0) && (alloc > param->maxalloc)) { alloc = param->maxalloc; } - if ((newalloc = realloc(param->memory, alloc)) == NULL) { + void *newalloc = param->secure ? calloc(1, alloc) : realloc(param->memory, alloc); + if (!newalloc) { return RNP_ERROR_OUT_OF_MEMORY; } - + if (param->secure) { + memcpy(newalloc, param->memory, dst->writeb); + secure_clear(param->memory, dst->writeb); + free(param->memory); + } param->memory = newalloc; param->allocated = alloc; } @@ -1021,14 +1007,18 @@ mem_dst_close(pgp_dest_t *dst, bool discard) { pgp_dest_mem_param_t *param = (pgp_dest_mem_param_t *) dst->param; + if (!param) { + return; + } - if (param) { - if (param->free) { - free(param->memory); + if (param->free) { + if (param->secure) { + secure_clear(param->memory, param->allocated); } - free(param); - dst->param = NULL; + free(param->memory); } + free(param); + dst->param = NULL; } rnp_result_t @@ -1046,6 +1036,7 @@ param->allocated = mem ? len : 0; param->memory = mem; param->free = !mem; + param->secure = false; dst->write = mem_dst_write; dst->close = mem_dst_close; @@ -1129,6 +1120,19 @@ return res; } +void +mem_dest_secure_memory(pgp_dest_t *dst, bool secure) +{ + if (!dst || (dst->type != PGP_STREAM_MEMORY)) { + RNP_LOG("wrong function call"); + return; + } + pgp_dest_mem_param_t *param = (pgp_dest_mem_param_t *) dst->param; + if (param) { + param->secure = secure; + } +} + static rnp_result_t null_dst_write(pgp_dest_t *dst, const void *buf, size_t len) { diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-common.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-common.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-common.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-common.h 2022-04-15 07:49:22.000000000 +0000 @@ -227,9 +227,10 @@ /** @brief get memory from the memory source * @param src initialized memory source + * @param own transfer ownership of the memory * @return pointer to the memory or NULL if it is not a memory source **/ -const void *mem_src_get_memory(pgp_source_t *src); +const void *mem_src_get_memory(pgp_source_t *src, bool own = false); typedef struct pgp_dest_t { pgp_dest_write_func_t * write; @@ -350,6 +351,13 @@ **/ void *mem_dest_own_memory(pgp_dest_t *dst); +/** @brief mark memory dest as secure, so it will be deallocated securely + * @param dst pre-allocated and initialized memory dest + * @param secure whether memory should be considered as secure or not + * @return void + **/ +void mem_dest_secure_memory(pgp_dest_t *dst, bool secure); + /** @brief init null destination which silently discards all the output * @param dst pre-allocated dest structure * @return RNP_SUCCESS or error code diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-ctx.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-ctx.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-ctx.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-ctx.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -30,13 +30,6 @@ #include "utils.h" #include "stream-ctx.h" -rng_t * -rnp_ctx_rng_handle(const rnp_ctx_t *ctx) -{ - assert(ctx->rng); - return ctx->rng; -} - rnp_result_t rnp_ctx_add_encryption_password(rnp_ctx_t & ctx, const char * password, @@ -50,8 +43,11 @@ info.s2k.specifier = PGP_S2KS_ITERATED_AND_SALTED; info.s2k.hash_alg = halg; - if (!rng_get_data(ctx.rng, info.s2k.salt, sizeof(info.s2k.salt))) { - return RNP_ERROR_GENERIC; + try { + ctx.ctx->rng.get(info.s2k.salt, sizeof(info.s2k.salt)); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_RNG; } if (iterations == 0) { iterations = pgp_s2k_compute_iters(halg, DEFAULT_S2K_MSEC, DEFAULT_S2K_TUNE_MSEC); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-ctx.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-ctx.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-ctx.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-ctx.h 2022-04-15 07:49:22.000000000 +0000 @@ -35,6 +35,7 @@ #include #include "pgp-key.h" #include "crypto/mem.h" +#include "sec_profile.hpp" typedef enum rnp_operation_t { RNP_OP_UNKNOWN = 0, @@ -111,7 +112,7 @@ std::list passwords{}; /* passwords to encrypt message */ std::list signers{}; /* keys to which sign message */ bool discard{}; /* discard the output */ - rng_t * rng{}; /* pointer to rng_t */ + rnp::SecurityContext * ctx{}; /* pointer to rnp::RNG */ rnp_operation_t operation{}; /* current operation type */ rnp_ctx_t() = default; @@ -122,8 +123,6 @@ rnp_ctx_t &operator=(rnp_ctx_t &&) = delete; } rnp_ctx_t; -struct rng_st_t *rnp_ctx_rng_handle(const rnp_ctx_t *ctx); - rnp_result_t rnp_ctx_add_encryption_password(rnp_ctx_t & ctx, const char * password, pgp_hash_alg_t halg, diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-def.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-def.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-def.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-def.h 2022-04-15 07:49:22.000000000 +0000 @@ -58,6 +58,7 @@ /* Maximum OpenPGP packet nesting level */ #define MAXIMUM_NESTING_LEVEL 32 +#define MAXIMUM_STREAM_PKTS 16 /* Maximum text line length supported by GnuPG */ #define MAXIMUM_GNUPG_LINELEN 19995 diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-dump.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-dump.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-dump.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-dump.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -46,12 +46,11 @@ #include "crypto/s2k.h" #include "fingerprint.h" #include "pgp-key.h" -#include "list.h" #include "crypto.h" -#include "json_utils.h" +#include "json-utils.h" #include -static pgp_map_t packet_tag_map[] = { +static const id_str_pair packet_tag_map[] = { {PGP_PKT_RESERVED, "Reserved"}, {PGP_PKT_PK_SESSION_KEY, "Public-Key Encrypted Session Key"}, {PGP_PKT_SIGNATURE, "Signature"}, @@ -73,11 +72,10 @@ {PGP_PKT_SE_IP_DATA, "Symmetric Encrypted and Integrity Protected Data"}, {PGP_PKT_MDC, "Modification Detection Code"}, {PGP_PKT_AEAD_ENCRYPTED, "AEAD Encrypted Data Packet"}, - - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t sig_type_map[] = { +static const id_str_pair sig_type_map[] = { {PGP_SIG_BINARY, "Signature of a binary document"}, {PGP_SIG_TEXT, "Signature of a canonical text document"}, {PGP_SIG_STANDALONE, "Standalone signature"}, @@ -93,10 +91,10 @@ {PGP_SIG_REV_CERT, "Certification revocation signature"}, {PGP_SIG_TIMESTAMP, "Timestamp signature"}, {PGP_SIG_3RD_PARTY, "Third-Party Confirmation signature"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t sig_subpkt_type_map[] = { +static const id_str_pair sig_subpkt_type_map[] = { {PGP_SIG_SUBPKT_CREATION_TIME, "signature creation time"}, {PGP_SIG_SUBPKT_EXPIRATION_TIME, "signature expiration time"}, {PGP_SIG_SUBPKT_EXPORT_CERT, "exportable certification"}, @@ -122,10 +120,10 @@ {PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE, "embedded signature"}, {PGP_SIG_SUBPKT_ISSUER_FPR, "issuer fingerprint"}, {PGP_SIG_SUBPKT_PREFERRED_AEAD, "preferred AEAD algorithms"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t key_type_map[] = { +static const id_str_pair key_type_map[] = { {PGP_PKT_SECRET_KEY, "Secret key"}, {PGP_PKT_PUBLIC_KEY, "Public key"}, {PGP_PKT_SECRET_SUBKEY, "Secret subkey"}, @@ -133,7 +131,7 @@ {0x00, NULL}, }; -static pgp_map_t pubkey_alg_map[] = { +static const id_str_pair pubkey_alg_map[] = { {PGP_PKA_RSA, "RSA (Encrypt or Sign)"}, {PGP_PKA_RSA_ENCRYPT_ONLY, "RSA (Encrypt-Only)"}, {PGP_PKA_RSA_SIGN_ONLY, "RSA (Sign-Only)"}, @@ -145,10 +143,10 @@ {PGP_PKA_RESERVED_DH, "Reserved for DH (X9.42)"}, {PGP_PKA_EDDSA, "EdDSA"}, {PGP_PKA_SM2, "SM2"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t symm_alg_map[] = { +static const id_str_pair symm_alg_map[] = { {PGP_SA_PLAINTEXT, "Plaintext"}, {PGP_SA_IDEA, "IDEA"}, {PGP_SA_TRIPLEDES, "TripleDES"}, @@ -162,10 +160,10 @@ {PGP_SA_CAMELLIA_192, "Camellia-192"}, {PGP_SA_CAMELLIA_256, "Camellia-256"}, {PGP_SA_SM4, "SM4"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t hash_alg_map[] = { +static const id_str_pair hash_alg_map[] = { {PGP_HASH_MD5, "MD5"}, {PGP_HASH_SHA1, "SHA1"}, {PGP_HASH_RIPEMD, "RIPEMD160"}, @@ -176,25 +174,25 @@ {PGP_HASH_SM3, "SM3"}, {PGP_HASH_SHA3_256, "SHA3-256"}, {PGP_HASH_SHA3_512, "SHA3-512"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t z_alg_map[] = { +static const id_str_pair z_alg_map[] = { {PGP_C_NONE, "Uncompressed"}, {PGP_C_ZIP, "ZIP"}, {PGP_C_ZLIB, "ZLib"}, {PGP_C_BZIP2, "BZip2"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t aead_alg_map[] = { +static const id_str_pair aead_alg_map[] = { {PGP_AEAD_NONE, "None"}, {PGP_AEAD_EAX, "EAX"}, {PGP_AEAD_OCB, "OCB"}, - {0x00, NULL}, /* this is the end-of-array marker */ + {0x00, NULL}, }; -static pgp_map_t revoc_reason_map[] = { +static const id_str_pair revoc_reason_map[] = { {PGP_REVOCATION_NO_REASON, "No reason"}, {PGP_REVOCATION_SUPERSEDED, "Superseded"}, {PGP_REVOCATION_COMPROMISED, "Compromised"}, @@ -325,7 +323,7 @@ static void dst_print_palg(pgp_dest_t *dst, const char *name, pgp_pubkey_alg_t palg) { - const char *palg_name = pgp_str_from_map(palg, pubkey_alg_map); + const char *palg_name = id_str_pair::lookup(pubkey_alg_map, palg, "Unknown"); if (!name) { name = "public key algorithm"; } @@ -336,7 +334,7 @@ static void dst_print_halg(pgp_dest_t *dst, const char *name, pgp_hash_alg_t halg) { - const char *halg_name = pgp_str_from_map(halg, hash_alg_map); + const char *halg_name = id_str_pair::lookup(hash_alg_map, halg, "Unknown"); if (!name) { name = "hash algorithm"; } @@ -347,7 +345,7 @@ static void dst_print_salg(pgp_dest_t *dst, const char *name, pgp_symm_alg_t salg) { - const char *salg_name = pgp_str_from_map(salg, symm_alg_map); + const char *salg_name = id_str_pair::lookup(symm_alg_map, salg, "Unknown"); if (!name) { name = "symmetric algorithm"; } @@ -358,7 +356,7 @@ static void dst_print_aalg(pgp_dest_t *dst, const char *name, pgp_aead_alg_t aalg) { - const char *aalg_name = pgp_str_from_map(aalg, aead_alg_map); + const char *aalg_name = id_str_pair::lookup(aead_alg_map, aalg, "Unknown"); if (!name) { name = "aead algorithm"; } @@ -369,7 +367,7 @@ static void dst_print_zalg(pgp_dest_t *dst, const char *name, pgp_compression_type_t zalg) { - const char *zalg_name = pgp_str_from_map(zalg, z_alg_map); + const char *zalg_name = id_str_pair::lookup(z_alg_map, zalg, "Unknown"); if (!name) { name = "compression algorithm"; } @@ -386,7 +384,8 @@ } static void -dst_print_algs(pgp_dest_t *dst, const char *name, uint8_t *algs, size_t algc, pgp_map_t map[]) +dst_print_algs( + pgp_dest_t *dst, const char *name, uint8_t *algs, size_t algc, const id_str_pair map[]) { if (!name) { name = "algorithms"; @@ -394,7 +393,8 @@ dst_printf(dst, "%s: ", name); for (size_t i = 0; i < algc; i++) { - dst_printf(dst, "%s%s", pgp_str_from_map(algs[i], map), i + 1 < algc ? ", " : ""); + dst_printf( + dst, "%s%s", id_str_pair::lookup(map, algs[i], "Unknown"), i + 1 < algc ? ", " : ""); } dst_printf(dst, " ("); for (size_t i = 0; i < algc; i++) { @@ -406,7 +406,7 @@ static void dst_print_sig_type(pgp_dest_t *dst, const char *name, pgp_sig_type_t sigtype) { - const char *sig_name = pgp_str_from_map(sigtype, sig_type_map); + const char *sig_name = id_str_pair::lookup(sig_type_map, sigtype, "Unknown"); if (!name) { name = "signature type"; } @@ -532,7 +532,7 @@ static void signature_dump_subpacket(rnp_dump_ctx_t *ctx, pgp_dest_t *dst, const pgp_sig_subpkt_t &subpkt) { - const char *sname = pgp_str_from_map(subpkt.type, sig_subpkt_type_map); + const char *sname = id_str_pair::lookup(sig_subpkt_type_map, subpkt.type, "Unknown"); switch (subpkt.type) { case PGP_SIG_SUBPKT_CREATION_TIME: @@ -577,8 +577,22 @@ case PGP_SIG_SUBPKT_ISSUER_KEY_ID: dst_print_hex(dst, sname, subpkt.fields.issuer, PGP_KEY_ID_SIZE, false); break; - case PGP_SIG_SUBPKT_NOTATION_DATA: + case PGP_SIG_SUBPKT_NOTATION_DATA: { + std::string name(subpkt.fields.notation.name, + subpkt.fields.notation.name + subpkt.fields.notation.nlen); + std::vector value(subpkt.fields.notation.value, + subpkt.fields.notation.value + subpkt.fields.notation.vlen); + if (subpkt.fields.notation.human) { + dst_printf(dst, "%s: %s = ", sname, name.c_str()); + dst_printf(dst, "%.*s\n", (int) value.size(), (char *) value.data()); + } else { + char hex[64]; + vsnprinthex(hex, sizeof(hex), value.data(), value.size()); + dst_printf(dst, "%s: %s = ", sname, name.c_str()); + dst_printf(dst, "0x%s (%zu bytes)\n", hex, value.size()); + } break; + } case PGP_SIG_SUBPKT_PREFERRED_HASH: dst_print_algs(dst, "preferred hash algorithms", @@ -626,7 +640,7 @@ break; case PGP_SIG_SUBPKT_REVOCATION_REASON: { int code = subpkt.fields.revocation_reason.code; - const char *reason = pgp_str_from_map(code, revoc_reason_map); + const char *reason = id_str_pair::lookup(revoc_reason_map, code, "Unknown"); dst_printf(dst, "%s: %d (%s)\n", sname, code, reason); dst_print_raw(dst, "message", @@ -799,7 +813,7 @@ return ret; } - dst_printf(dst, "%s packet\n", pgp_str_from_map(key.tag, key_type_map)); + dst_printf(dst, "%s packet\n", id_str_pair::lookup(key_type_map, key.tag, "Unknown")); indent_dest_increase(dst); dst_printf(dst, "version: %d\n", (int) key.version); @@ -1225,7 +1239,7 @@ /* do not allow endless recursion */ if (++ctx->layers > MAXIMUM_NESTING_LEVEL) { RNP_LOG("Too many OpenPGP nested layers during the dump."); - dst_printf(dst, ":too many OpenPGP packet layers, stopping."); + dst_printf(dst, ":too many OpenPGP packet layers, stopping.\n"); ret = RNP_SUCCESS; goto finish; } @@ -1300,15 +1314,18 @@ case PGP_PKT_SE_DATA: case PGP_PKT_SE_IP_DATA: case PGP_PKT_AEAD_ENCRYPTED: + ctx->stream_pkts++; ret = stream_dump_encrypted(src, dst, hdr.tag); break; case PGP_PKT_ONE_PASS_SIG: ret = stream_dump_one_pass(src, dst); break; case PGP_PKT_COMPRESSED: + ctx->stream_pkts++; ret = stream_dump_compressed(ctx, src, dst); break; case PGP_PKT_LITDATA: + ctx->stream_pkts++; ret = stream_dump_literal(src, dst); break; case PGP_PKT_MARKER: @@ -1328,6 +1345,13 @@ RNP_LOG("failed to process packet"); goto finish; } + + if (ctx->stream_pkts > MAXIMUM_STREAM_PKTS) { + RNP_LOG("Too many OpenPGP stream packets during the dump."); + dst_printf(dst, ":too many OpenPGP stream packets, stopping.\n"); + ret = RNP_SUCCESS; + goto finish; + } } ret = RNP_SUCCESS; @@ -1369,6 +1393,7 @@ rnp_result_t ret = RNP_ERROR_GENERIC; ctx->layers = 0; + ctx->stream_pkts = 0; /* check whether source is cleartext - then skip till the signature */ if (is_cleartext_source(src)) { dst_printf(dst, ":cleartext signed data\n"); @@ -1400,11 +1425,9 @@ goto finish; } indent = true; - indent_dest_set(&wrdst, 0); ret = stream_dump_packets_raw(ctx, src, &wrdst); - finish: if (armored) { src_close(&armorsrc); @@ -1416,7 +1439,7 @@ } static bool -obj_add_intstr_json(json_object *obj, const char *name, int val, pgp_map_t map[]) +obj_add_intstr_json(json_object *obj, const char *name, int val, const id_str_pair map[]) { if (!obj_add_field_json(obj, name, json_object_new_int(val))) { return false; @@ -1425,7 +1448,7 @@ return true; } char namestr[64] = {0}; - const char *str = pgp_str_from_map(val, map); + const char *str = id_str_pair::lookup(map, val, "Unknown"); snprintf(namestr, sizeof(namestr), "%s.str", name); return obj_add_field_json(obj, namestr, json_object_new_string(str)); } @@ -1447,7 +1470,7 @@ static bool subpacket_obj_add_algs( - json_object *obj, const char *name, uint8_t *algs, size_t len, pgp_map_t map[]) + json_object *obj, const char *name, uint8_t *algs, size_t len, const id_str_pair map[]) { json_object *jso_algs = json_object_new_array(); if (!jso_algs || !obj_add_field_json(obj, name, jso_algs)) { @@ -1470,8 +1493,9 @@ return false; } for (size_t i = 0; i < len; i++) { - if (!array_add_element_json(jso_algs, - json_object_new_string(pgp_str_from_map(algs[i], map)))) { + if (!array_add_element_json( + jso_algs, + json_object_new_string(id_str_pair::lookup(map, algs[i], "Unknown")))) { return false; } } @@ -1683,7 +1707,23 @@ case PGP_SIG_SUBPKT_ISSUER_FPR: return obj_add_hex_json( obj, "fingerprint", subpkt.fields.issuer_fp.fp, subpkt.fields.issuer_fp.len); - case PGP_SIG_SUBPKT_NOTATION_DATA: + case PGP_SIG_SUBPKT_NOTATION_DATA: { + bool human = subpkt.fields.notation.human; + if (!json_add(obj, "human", human) || !json_add(obj, + "name", + (char *) subpkt.fields.notation.name, + subpkt.fields.notation.nlen)) { + return false; + } + if (human) { + return json_add(obj, + "value", + (char *) subpkt.fields.notation.value, + subpkt.fields.notation.vlen); + } + return obj_add_hex_json( + obj, "value", subpkt.fields.notation.value, subpkt.fields.notation.vlen); + } default: if (!ctx->dump_packets) { return obj_add_hex_json(obj, "raw", subpkt.data, subpkt.len); @@ -2386,15 +2426,18 @@ case PGP_PKT_SE_DATA: case PGP_PKT_SE_IP_DATA: case PGP_PKT_AEAD_ENCRYPTED: + ctx->stream_pkts++; ret = stream_dump_encrypted_json(src, pkt, hdr.tag); break; case PGP_PKT_ONE_PASS_SIG: ret = stream_dump_one_pass_json(src, pkt); break; case PGP_PKT_COMPRESSED: + ctx->stream_pkts++; ret = stream_dump_compressed_json(ctx, src, pkt); break; case PGP_PKT_LITDATA: + ctx->stream_pkts++; ret = stream_dump_literal_json(src, pkt); break; case PGP_PKT_MARKER: @@ -2417,6 +2460,12 @@ ret = RNP_ERROR_OUT_OF_MEMORY; goto done; } + if (ctx->stream_pkts > MAXIMUM_STREAM_PKTS) { + RNP_LOG("Too many OpenPGP stream packets during the dump."); + ret = RNP_SUCCESS; + goto done; + } + pkt = NULL; } done: diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-dump.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-dump.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-dump.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-dump.h 2022-04-15 07:49:22.000000000 +0000 @@ -40,6 +40,7 @@ bool dump_packets; bool dump_grips; size_t layers; + size_t stream_pkts; } rnp_dump_ctx_t; rnp_result_t stream_dump_packets(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-key.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-key.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-key.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-key.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -50,6 +50,7 @@ #include "../librekey/key_store_pgp.h" #include #include +#include /** * @brief Add signatures from src to dst, skipping the duplicates. @@ -209,356 +210,6 @@ return RNP_SUCCESS; } -pgp_transferable_userid_t * -transferable_key_add_userid(pgp_transferable_key_t &key, const char *userid) -{ - try { - key.userids.emplace_back(); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return NULL; - } - - pgp_transferable_userid_t &uid = key.userids.back(); - uid.uid.tag = PGP_PKT_USER_ID; - uid.uid.uid_len = strlen(userid); - if (!(uid.uid.uid = (uint8_t *) malloc(uid.uid.uid_len))) { - key.userids.pop_back(); - return NULL; - } - memcpy(uid.uid.uid, userid, uid.uid.uid_len); - return &uid; -} - -bool -signature_calculate_certification(const pgp_key_pkt_t * key, - const pgp_userid_pkt_t *uid, - pgp_signature_t * sig, - const pgp_key_pkt_t * signer) -{ - if (!key || !uid || !sig || !signer) { - RNP_LOG("NULL parameter(s)"); - return false; - } - - rng_t rng = {}; - if (!rng_init(&rng, RNG_SYSTEM)) { - RNP_LOG("RNG init failed"); - return false; - } - - pgp_hash_t hash = {}; - bool res = signature_fill_hashed_data(sig) && - signature_hash_certification(sig, key, uid, &hash) && - !signature_calculate(sig, &signer->material, &hash, &rng); - rng_destroy(&rng); - return res; -} - -bool -signature_calculate_direct(const pgp_key_pkt_t *key, - pgp_signature_t * sig, - const pgp_key_pkt_t *signer) -{ - if (!key || !sig || !signer) { - RNP_LOG("NULL parameter(s)"); - return false; - } - - rng_t rng = {}; - if (!rng_init(&rng, RNG_SYSTEM)) { - RNP_LOG("RNG init failed"); - return false; - } - - pgp_hash_t hash = {}; - bool res = signature_fill_hashed_data(sig) && signature_hash_direct(sig, key, &hash) && - !signature_calculate(sig, &signer->material, &hash, &rng); - rng_destroy(&rng); - return res; -} - -pgp_signature_t * -transferable_userid_certify(const pgp_key_pkt_t & key, - pgp_transferable_userid_t & userid, - const pgp_key_pkt_t & signer, - pgp_hash_alg_t hash_alg, - const rnp_selfsig_cert_info_t &cert) -{ - pgp_signature_t sig; - pgp_key_id_t keyid = {}; - pgp_fingerprint_t keyfp; - - if (pgp_keyid(keyid, signer)) { - RNP_LOG("failed to calculate keyid"); - return NULL; - } - - if (pgp_fingerprint(keyfp, signer)) { - RNP_LOG("failed to calculate keyfp"); - return NULL; - } - - sig.version = PGP_V4; - sig.halg = pgp_hash_adjust_alg_to_key(hash_alg, &signer); - sig.palg = signer.alg; - sig.set_type(PGP_CERT_POSITIVE); - - try { - sig.set_keyfp(keyfp); - sig.set_creation(time(NULL)); - if (cert.key_expiration) { - sig.set_key_expiration(cert.key_expiration); - } - if (cert.key_flags) { - sig.set_key_flags(cert.key_flags); - } - if (cert.primary) { - sig.set_primary_uid(true); - } - if (!cert.prefs.symm_algs.empty()) { - sig.set_preferred_symm_algs(cert.prefs.symm_algs); - } - if (!cert.prefs.hash_algs.empty()) { - sig.set_preferred_hash_algs(cert.prefs.hash_algs); - } - if (!cert.prefs.z_algs.empty()) { - sig.set_preferred_z_algs(cert.prefs.z_algs); - } - if (!cert.prefs.ks_prefs.empty()) { - sig.set_key_server_prefs(cert.prefs.ks_prefs[0]); - } - if (!cert.prefs.key_server.empty()) { - sig.set_key_server(cert.prefs.key_server); - } - sig.set_keyid(keyid); - } catch (const std::exception &e) { - RNP_LOG("failed to setup signature: %s", e.what()); - return NULL; - } - - if (!signature_calculate_certification(&key, &userid.uid, &sig, &signer)) { - RNP_LOG("failed to calculate signature"); - return NULL; - } - try { - userid.signatures.emplace_back(std::move(sig)); - return &userid.signatures.back(); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return NULL; - } -} - -static bool -signature_calculate_primary_binding(const pgp_key_pkt_t *key, - const pgp_key_pkt_t *subkey, - pgp_hash_alg_t halg, - pgp_signature_t * sig, - rng_t * rng) -{ - pgp_key_id_t keyid = {}; - pgp_hash_t hash = {}; - bool res = false; - - sig->version = PGP_V4; - sig->halg = pgp_hash_adjust_alg_to_key(halg, subkey); - sig->palg = subkey->alg; - sig->set_type(PGP_SIG_PRIMARY); - - if (pgp_keyid(keyid, *subkey)) { - RNP_LOG("failed to calculate keyid"); - return false; - } - try { - sig->set_creation(time(NULL)); - sig->set_keyid(keyid); - } catch (const std::exception &e) { - RNP_LOG("failed to setup embedded signature: %s", e.what()); - return false; - } - if (!signature_hash_binding(sig, key, subkey, &hash)) { - RNP_LOG("failed to hash key and subkey"); - goto end; - } - if (!signature_fill_hashed_data(sig)) { - RNP_LOG("failed to hash signature"); - goto end; - } - if (signature_calculate(sig, &subkey->material, &hash, rng)) { - RNP_LOG("failed to calculate signature"); - goto end; - } - res = true; -end: - if (!res) { - pgp_hash_finish(&hash, NULL); - } - return res; -} - -bool -signature_calculate_binding(const pgp_key_pkt_t *key, - const pgp_key_pkt_t *sub, - pgp_signature_t * sig, - bool subsign) -{ - pgp_hash_t hash = {}; - rng_t rng = {}; - pgp_key_id_t keyid; - - if (pgp_keyid(keyid, *key)) { - RNP_LOG("failed to calculate keyid"); - return false; - } - - if (!rng_init(&rng, RNG_SYSTEM)) { - RNP_LOG("RNG init failed"); - return false; - } - - bool res = false; - if (!signature_fill_hashed_data(sig) || !signature_hash_binding(sig, key, sub, &hash)) { - RNP_LOG("failed to hash signature"); - goto end; - } - - if (signature_calculate(sig, &key->material, &hash, &rng)) { - RNP_LOG("failed to calculate signature"); - goto end; - } - - /* unhashed subpackets. Primary key binding signature and issuer key id */ - if (subsign) { - pgp_signature_t embsig; - - if (!signature_calculate_primary_binding(key, sub, sig->halg, &embsig, &rng)) { - RNP_LOG("failed to calculate primary key binding signature"); - goto end; - } - if (!signature_set_embedded_sig(sig, &embsig)) { - RNP_LOG("failed to add primary key binding signature"); - goto end; - } - } - - /* add keyid since it should (probably) be after the primary key binding if any */ - try { - sig->set_keyid(keyid); - } catch (const std::exception &e) { - RNP_LOG("failed to set issuer key id: %s", e.what()); - goto end; - } - res = true; -end: - rng_destroy(&rng); - return res; -} - -pgp_signature_t * -transferable_subkey_bind(const pgp_key_pkt_t & key, - pgp_transferable_subkey_t & subkey, - pgp_hash_alg_t hash_alg, - const rnp_selfsig_binding_info_t &binding) -{ - pgp_fingerprint_t keyfp; - if (pgp_fingerprint(keyfp, key)) { - RNP_LOG("failed to calculate keyfp"); - return NULL; - } - - pgp_signature_t sig; - pgp_key_flags_t realkf = (pgp_key_flags_t) 0; - - sig.version = PGP_V4; - sig.halg = pgp_hash_adjust_alg_to_key(hash_alg, &key); - sig.palg = key.alg; - sig.set_type(PGP_SIG_SUBKEY); - - try { - sig.set_keyfp(keyfp); - sig.set_creation(time(NULL)); - if (binding.key_expiration) { - sig.set_key_expiration(binding.key_expiration); - } - if (binding.key_flags) { - sig.set_key_flags(binding.key_flags); - } - } catch (const std::exception &e) { - RNP_LOG("failed to setup signature: %s", e.what()); - return NULL; - } - - realkf = (pgp_key_flags_t) binding.key_flags; - if (!realkf) { - realkf = pgp_pk_alg_capabilities(subkey.subkey.alg); - } - - if (!signature_calculate_binding(&key, &subkey.subkey, &sig, realkf & PGP_KF_SIGN)) { - return NULL; - } - try { - subkey.signatures.emplace_back(std::move(sig)); - return &subkey.signatures.back(); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return NULL; - } -} - -pgp_signature_t * -transferable_key_revoke(const pgp_key_pkt_t &key, - const pgp_key_pkt_t &signer, - pgp_hash_alg_t hash_alg, - const pgp_revoke_t & revoke) -{ - pgp_signature_t sig; - bool res = false; - pgp_key_id_t keyid; - pgp_fingerprint_t keyfp; - - if (pgp_keyid(keyid, signer)) { - RNP_LOG("failed to calculate keyid"); - return NULL; - } - if (pgp_fingerprint(keyfp, signer)) { - RNP_LOG("failed to calculate keyfp"); - return NULL; - } - - sig.version = PGP_V4; - sig.halg = pgp_hash_adjust_alg_to_key(hash_alg, &signer); - sig.palg = signer.alg; - sig.set_type(is_primary_key_pkt(key.tag) ? PGP_SIG_REV_KEY : PGP_SIG_REV_SUBKEY); - - try { - sig.set_keyfp(keyfp); - sig.set_creation(time(NULL)); - sig.set_revocation_reason(revoke.code, revoke.reason); - sig.set_keyid(keyid); - } catch (const std::exception &e) { - RNP_LOG("failed to setup signature: %s", e.what()); - return NULL; - } - - if (is_primary_key_pkt(key.tag)) { - res = signature_calculate_direct(&key, &sig, &signer); - } else { - res = signature_calculate_binding(&signer, &key, &sig, false); - } - if (!res) { - RNP_LOG("failed to calculate signature"); - return NULL; - } - - try { - return new pgp_signature_t(std::move(sig)); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return NULL; - } -} - static bool skip_pgp_packets(pgp_source_t *src, const std::set &pkts) { @@ -1016,8 +667,9 @@ for (size_t idx = 0; idx < len; idx++) { sum += mpis[idx]; } - if (sum != read_uint16(mpis + len)) { - RNP_LOG("wrong key checksum"); + uint16_t expsum = read_uint16(mpis + len); + if (sum != expsum) { + RNP_LOG("Wrong key checksum, got 0x%X instead of 0x%X.", (int) sum, (int) expsum); return RNP_ERROR_DECRYPT_FAILED; } break; @@ -1028,15 +680,17 @@ return RNP_ERROR_BAD_FORMAT; } /* calculate and check sha1 hash of the cleartext */ - pgp_hash_t hash; - uint8_t hval[PGP_MAX_HASH_SIZE]; - - if (!pgp_hash_create(&hash, PGP_HASH_SHA1)) { - return RNP_ERROR_BAD_STATE; - } - len -= PGP_SHA1_HASH_SIZE; - pgp_hash_add(&hash, mpis, len); - if (pgp_hash_finish(&hash, hval) != PGP_SHA1_HASH_SIZE) { + uint8_t hval[PGP_SHA1_HASH_SIZE]; + try { + rnp::Hash hash(PGP_HASH_SHA1); + assert(hash.size() == sizeof(hval)); + len -= PGP_SHA1_HASH_SIZE; + hash.add(mpis, len); + if (hash.finish(hval) != PGP_SHA1_HASH_SIZE) { + return RNP_ERROR_BAD_STATE; + } + } catch (const std::exception &e) { + RNP_LOG("hash calculation failed: %s", e.what()); return RNP_ERROR_BAD_STATE; } if (memcmp(hval, mpis + len, PGP_SHA1_HASH_SIZE)) { @@ -1111,6 +765,8 @@ if (!is_secret_key_pkt(key->tag)) { return RNP_ERROR_BAD_PARAMETERS; } + /* mark material as not validated as it may be valid for public part */ + key->material.validity.reset(); /* check whether data is not encrypted */ if (!key->sec_protection.s2k.usage) { @@ -1222,14 +878,11 @@ } /* add sha1 hash */ - pgp_hash_t hash; - if (!pgp_hash_create(&hash, PGP_HASH_SHA1)) { - RNP_LOG("failed to create sha1 hash"); - throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); - } - pgp_hash_add(&hash, body.data(), body.size()); - uint8_t hval[PGP_MAX_HASH_SIZE]; - if (pgp_hash_finish(&hash, hval) != PGP_SHA1_HASH_SIZE) { + rnp::Hash hash(PGP_HASH_SHA1); + hash.add(body.data(), body.size()); + uint8_t hval[PGP_SHA1_HASH_SIZE]; + assert(sizeof(hval) == hash.size()); + if (hash.finish(hval) != PGP_SHA1_HASH_SIZE) { RNP_LOG("failed to finish hash"); throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); } @@ -1237,7 +890,7 @@ } rnp_result_t -encrypt_secret_key(pgp_key_pkt_t *key, const char *password, rng_t *rng) +encrypt_secret_key(pgp_key_pkt_t *key, const char *password, rnp::RNG &rng) { if (!is_secret_key_pkt(key->tag) || !key->material.secret) { return RNP_ERROR_BAD_PARAMETERS; @@ -1280,23 +933,9 @@ return RNP_ERROR_BAD_PARAMETERS; } /* generate iv and s2k salt */ - if (rng) { - if (!rng_get_data(rng, key->sec_protection.iv, blsize)) { - return RNP_ERROR_RNG; - } - if ((key->sec_protection.s2k.specifier != PGP_S2KS_SIMPLE) && - !rng_get_data(rng, key->sec_protection.s2k.salt, PGP_SALT_SIZE)) { - return RNP_ERROR_RNG; - } - } else { - /* temporary solution! */ - if (!rng_generate(key->sec_protection.iv, blsize)) { - return RNP_ERROR_RNG; - } - if ((key->sec_protection.s2k.specifier != PGP_S2KS_SIMPLE) && - !rng_generate(key->sec_protection.s2k.salt, PGP_SALT_SIZE)) { - return RNP_ERROR_RNG; - } + rng.get(key->sec_protection.iv, blsize); + if ((key->sec_protection.s2k.specifier != PGP_S2KS_SIMPLE)) { + rng.get(key->sec_protection.s2k.salt, PGP_SALT_SIZE); } /* derive key */ rnp::secure_array keybuf; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-key.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-key.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-key.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-key.h 2022-04-15 07:49:22.000000000 +0000 @@ -115,25 +115,6 @@ rnp_result_t transferable_subkey_merge(pgp_transferable_subkey_t & dst, const pgp_transferable_subkey_t &src); -pgp_transferable_userid_t *transferable_key_add_userid(pgp_transferable_key_t &key, - const char * userid); - -pgp_signature_t *transferable_userid_certify(const pgp_key_pkt_t & key, - pgp_transferable_userid_t & userid, - const pgp_key_pkt_t & signer, - pgp_hash_alg_t hash_alg, - const rnp_selfsig_cert_info_t &cert); - -pgp_signature_t *transferable_subkey_bind(const pgp_key_pkt_t & primary_key, - pgp_transferable_subkey_t & subkey, - pgp_hash_alg_t hash_alg, - const rnp_selfsig_binding_info_t &binding); - -pgp_signature_t *transferable_key_revoke(const pgp_key_pkt_t &key, - const pgp_key_pkt_t &signer, - pgp_hash_alg_t hash_alg, - const pgp_revoke_t & revoke); - /* Process single primary key or subkey, skipping all key-related packets on error. If key.key.tag is zero, then (on success) result is subkey and it is stored in key.subkeys[0]. @@ -159,22 +140,8 @@ rnp_result_t decrypt_secret_key(pgp_key_pkt_t *key, const char *password); -rnp_result_t encrypt_secret_key(pgp_key_pkt_t *key, const char *password, rng_t *rng); +rnp_result_t encrypt_secret_key(pgp_key_pkt_t *key, const char *password, rnp::RNG &rng); void forget_secret_key_fields(pgp_key_material_t *key); -bool signature_calculate_certification(const pgp_key_pkt_t * key, - const pgp_userid_pkt_t *uid, - pgp_signature_t * sig, - const pgp_key_pkt_t * signer); - -bool signature_calculate_direct(const pgp_key_pkt_t *key, - pgp_signature_t * sig, - const pgp_key_pkt_t *signer); - -bool signature_calculate_binding(const pgp_key_pkt_t *key, - const pgp_key_pkt_t *sub, - pgp_signature_t * sig, - bool subsign); - #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-packet.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-packet.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-packet.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-packet.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -564,7 +564,7 @@ bool pgp_packet_body_t::get(pgp_mpi_t &val) noexcept { - uint16_t bits; + uint16_t bits = 0; if (!get(bits)) { return false; } @@ -582,14 +582,12 @@ return false; } /* check the mpi bit count */ - unsigned hbits = bits & 7 ? bits & 7 : 8; - if ((((unsigned) val.mpi[0] >> hbits) != 0) || - !((unsigned) val.mpi[0] & (1U << (hbits - 1)))) { - RNP_LOG("Warning! Wrong mpi bit count: got %" PRIu16 ", but high byte is %" PRIu8, - bits, - val.mpi[0]); - } val.len = len; + size_t mbits = mpi_bits(&val); + if (mbits != bits) { + RNP_LOG( + "Warning! Wrong mpi bit count: got %" PRIu16 ", but actual is %zu", bits, mbits); + } return true; } @@ -886,10 +884,10 @@ pgp_packet_body_t::write(pgp_dest_t &dst, bool hdr) noexcept { if (hdr) { - uint8_t hdr[6] = { + uint8_t hdrbt[6] = { (uint8_t)(tag_ | PGP_PTAG_ALWAYS_SET | PGP_PTAG_NEW_FORMAT), 0, 0, 0, 0, 0}; - size_t hlen = 1 + write_packet_len(&hdr[1], data_.size()); - dst_write(&dst, hdr, hlen); + size_t hlen = 1 + write_packet_len(&hdrbt[1], data_.size()); + dst_write(&dst, hdrbt, hlen); } dst_write(&dst, data_.data(), data_.size()); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-parse.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-parse.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-parse.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-parse.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -92,7 +92,7 @@ bool aead; /* AEAD encrypted data packet, tag 20 */ bool aead_validated; /* we read and validated last chunk */ pgp_crypt_t decrypt; /* decrypting crypto */ - pgp_hash_t mdc; /* mdc SHA1 hash */ + rnp::Hash mdc; /* mdc SHA1 hash */ size_t chunklen; /* size of AEAD chunk in bytes */ size_t chunkin; /* number of bytes read from the current chunk */ size_t chunkidx; /* index of the current chunk */ @@ -125,11 +125,11 @@ std::vector onepasses; /* list of one-pass singatures */ std::list sigs; /* list of signatures */ std::vector siginfos; /* signature validation info */ - std::vector hashes; /* hash contexts */ - std::vector txt_hashes; /* hash contexts for text-mode sigs */ + rnp::HashList hashes; /* hash contexts */ + rnp::HashList txt_hashes; /* hash contexts for text-mode sigs */ pgp_source_signed_param_t() = default; - ~pgp_source_signed_param_t(); + ~pgp_source_signed_param_t() = default; } pgp_source_signed_param_t; typedef struct pgp_source_compressed_param_t { @@ -314,7 +314,7 @@ compressed_src_read(pgp_source_t *src, void *buf, size_t len, size_t *readres) { pgp_source_compressed_param_t *param = (pgp_source_compressed_param_t *) src->param; - if (param == NULL) { + if (!param) { return false; } @@ -323,6 +323,13 @@ return true; } + if (param->alg == PGP_C_NONE) { + if (!src_read(param->pkt.readsrc, buf, len, readres)) { + RNP_LOG("failed to read uncompressed data"); + return false; + } + return true; + } if ((param->alg == PGP_C_ZIP) || (param->alg == PGP_C_ZLIB)) { param->z.next_out = (Bytef *) buf; param->z.avail_out = len; @@ -434,6 +441,7 @@ src->param = NULL; } +#if defined(ENABLE_AEAD) static bool encrypted_start_aead_chunk(pgp_source_encrypted_param_t *param, size_t idx, bool last) { @@ -469,9 +477,6 @@ /* set chunk index for nonce */ nlen = pgp_cipher_aead_nonce(param->aead_hdr.aalg, param->aead_hdr.iv, nonce, idx); - RNP_DHEX("authenticated data: ", param->aead_ad, param->aead_adlen); - RNP_DHEX("nonce: ", nonce, nlen); - /* start cipher */ return pgp_cipher_aead_start(¶m->decrypt, nonce, nlen); } @@ -544,8 +549,6 @@ src_skip(param->pkt.readsrc, tagread - taglen); } - RNP_DHEX("tag: ", param->cache + read + tagread - 2 * taglen, taglen); - res = pgp_cipher_aead_finish( ¶m->decrypt, param->cache, param->cache, read + tagread - taglen); if (!res) { @@ -554,8 +557,6 @@ } param->cachelen = read + tagread - 2 * taglen; param->chunkin += param->cachelen; - - RNP_DHEX("decrypted data: ", param->cache, param->cachelen); } size_t chunkidx = param->chunkidx; @@ -574,9 +575,6 @@ } size_t off = read + tagread - taglen; - - RNP_DHEX("tag: ", param->cache + off, taglen); - res = pgp_cipher_aead_finish( ¶m->decrypt, param->cache + off, param->cache + off, taglen); if (!res) { @@ -588,10 +586,14 @@ return res; } +#endif static bool encrypted_src_read_aead(pgp_source_t *src, void *buf, size_t len, size_t *read) { +#if !defined(ENABLE_AEAD) + return false; +#else pgp_source_encrypted_param_t *param = (pgp_source_encrypted_param_t *) src->param; size_t cbytes; size_t left = len; @@ -623,6 +625,7 @@ *read = len - left; return true; +#endif } static bool @@ -670,25 +673,30 @@ pgp_cipher_cfb_decrypt(¶m->decrypt, (uint8_t *) buf, (uint8_t *) buf, read); if (param->has_mdc) { - pgp_hash_add(¶m->mdc, buf, read); + try { + param->mdc.add(buf, read); - if (parsemdc) { - pgp_cipher_cfb_decrypt(¶m->decrypt, mdcbuf, mdcbuf, MDC_V1_SIZE); - pgp_cipher_cfb_finish(¶m->decrypt); - pgp_hash_add(¶m->mdc, mdcbuf, 2); - uint8_t hash[PGP_SHA1_HASH_SIZE] = {0}; - pgp_hash_finish(¶m->mdc, hash); + if (parsemdc) { + pgp_cipher_cfb_decrypt(¶m->decrypt, mdcbuf, mdcbuf, MDC_V1_SIZE); + pgp_cipher_cfb_finish(¶m->decrypt); + param->mdc.add(mdcbuf, 2); + uint8_t hash[PGP_SHA1_HASH_SIZE] = {0}; + param->mdc.finish(hash); - if ((mdcbuf[0] != MDC_PKT_TAG) || (mdcbuf[1] != MDC_V1_SIZE - 2)) { - RNP_LOG("mdc header check failed"); - return false; - } + if ((mdcbuf[0] != MDC_PKT_TAG) || (mdcbuf[1] != MDC_V1_SIZE - 2)) { + RNP_LOG("mdc header check failed"); + return false; + } - if (memcmp(&mdcbuf[2], hash, PGP_SHA1_HASH_SIZE) != 0) { - RNP_LOG("mdc hash check failed"); - return false; + if (memcmp(&mdcbuf[2], hash, PGP_SHA1_HASH_SIZE) != 0) { + RNP_LOG("mdc hash check failed"); + return false; + } + param->mdc_validated = true; } - param->mdc_validated = true; + } catch (const std::exception &e) { + RNP_LOG("mdc update failed: %s", e.what()); + return false; } } *readres = read; @@ -737,7 +745,9 @@ } if (param->aead) { +#if defined(ENABLE_AEAD) pgp_cipher_aead_destroy(¶m->decrypt); +#endif } else { pgp_cipher_cfb_finish(¶m->decrypt); } @@ -746,41 +756,69 @@ src->param = NULL; } -static bool +static void add_hash_for_sig(pgp_source_signed_param_t *param, pgp_sig_type_t stype, pgp_hash_alg_t halg) { /* Cleartext always uses param->hashes instead of param->txt_hashes */ if (!param->cleartext && (stype == PGP_SIG_TEXT)) { - return pgp_hash_list_add(param->txt_hashes, halg); + param->txt_hashes.add_alg(halg); } - return pgp_hash_list_add(param->hashes, halg); + param->hashes.add_alg(halg); } -static const pgp_hash_t * -get_hash_for_sig(pgp_source_signed_param_t *param, pgp_signature_info_t *sinfo) +static const rnp::Hash * +get_hash_for_sig(pgp_source_signed_param_t ¶m, pgp_signature_info_t &sinfo) { /* Cleartext always uses param->hashes instead of param->txt_hashes */ - if (!param->cleartext && (sinfo->sig->type() == PGP_SIG_TEXT)) { - return pgp_hash_list_get(param->txt_hashes, sinfo->sig->halg); + if (!param.cleartext && (sinfo.sig->type() == PGP_SIG_TEXT)) { + return param.txt_hashes.get(sinfo.sig->halg); } - return pgp_hash_list_get(param->hashes, sinfo->sig->halg); + return param.hashes.get(sinfo.sig->halg); } static void -signed_validate_signature(pgp_source_signed_param_t *param, pgp_signature_info_t *sinfo) +signed_validate_signature(pgp_source_signed_param_t ¶m, pgp_signature_info_t &sinfo) { - pgp_hash_t shash = {}; - + /* Find signing key */ + pgp_key_request_ctx_t keyctx = { + .op = PGP_OP_VERIFY, .secret = false, .search = {.type = PGP_KEY_SEARCH_FINGERPRINT}}; + + /* Get signer's fp or keyid */ + if (sinfo.sig->has_keyfp()) { + keyctx.search.by.fingerprint = sinfo.sig->keyfp(); + } else if (sinfo.sig->has_keyid()) { + keyctx.search.type = PGP_KEY_SEARCH_KEYID; + keyctx.search.by.keyid = sinfo.sig->keyid(); + } else { + RNP_LOG("cannot get signer's key fp or id from signature."); + sinfo.unknown = true; + return; + } + /* Get the public key */ + pgp_key_t *key = pgp_request_key(param.handler->key_provider, &keyctx); + if (!key) { + /* fallback to secret key */ + keyctx.secret = true; + if (!(key = pgp_request_key(param.handler->key_provider, &keyctx))) { + RNP_LOG("signer's key not found"); + sinfo.no_signer = true; + return; + } + } /* Get the hash context and clone it. */ - const pgp_hash_t *hash = get_hash_for_sig(param, sinfo); - if (!hash || !pgp_hash_copy(&shash, hash)) { - RNP_LOG("failed to clone hash context"); - sinfo->valid = false; + const rnp::Hash *hash = get_hash_for_sig(param, sinfo); + if (!hash) { + RNP_LOG("failed to get hash context."); return; } - - /* fill the signature info */ - signature_check(sinfo, &shash); + try { + rnp::Hash shash; + hash->clone(shash); + key->validate_sig(sinfo, shash, *param.handler->ctx->ctx); + } catch (const std::exception &e) { + RNP_LOG("Signature validation failed: %s", e.what()); + sinfo.valid = false; + } } static long @@ -808,7 +846,11 @@ signed_src_update(src, &last, 1); } pgp_source_signed_param_t *param = (pgp_source_signed_param_t *) src->param; - pgp_hash_list_update(param->hashes, buf, len); + try { + param->hashes.add(buf, len); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + } /* update text-mode sig hashes */ if (param->txt_hashes.empty()) { return; @@ -823,7 +865,11 @@ if (*ch != CH_LF) { if (*ch != CH_CR && param->stripped_crs > 0) { while (param->stripped_crs--) { - pgp_hash_list_update(param->txt_hashes, ST_CR, 1); + try { + param->txt_hashes.add(ST_CR, 1); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + } } param->stripped_crs = 0; } @@ -845,12 +891,19 @@ if (ch > linebeg) { long stripped_len = stripped_line_len(linebeg, ch); if (stripped_len > 0) { - pgp_hash_list_update(param->txt_hashes, linebeg, stripped_len); + try { + param->txt_hashes.add(linebeg, stripped_len); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + } } } /* dump EOL */ - pgp_hash_list_update(param->txt_hashes, ST_CRLF, 2); - + try { + param->txt_hashes.add(ST_CRLF, 2); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + } ch++; linebeg = ch; } @@ -861,7 +914,11 @@ param->stripped_crs = end - linebeg - stripped_len; } if (stripped_len > 0) { - pgp_hash_list_update(param->txt_hashes, linebeg, stripped_len); + try { + param->txt_hashes.add(linebeg, stripped_len); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + } } } } @@ -887,6 +944,8 @@ src->param = NULL; } +#define MAX_SIGNATURES 16384 + static rnp_result_t signed_read_single_signature(pgp_source_signed_param_t *param, pgp_source_t * readsrc, @@ -904,6 +963,11 @@ return RNP_ERROR_BAD_FORMAT; } + if (param->siginfos.size() >= MAX_SIGNATURES) { + RNP_LOG("Too many signatures in the stream."); + return RNP_ERROR_BAD_FORMAT; + } + try { param->siginfos.emplace_back(); pgp_signature_info_t &siginfo = param->siginfos.back(); @@ -978,8 +1042,6 @@ signed_src_finish(pgp_source_t *src) { pgp_source_signed_param_t *param = (pgp_source_signed_param_t *) src->param; - pgp_key_request_ctx_t keyctx; - pgp_key_t * key = NULL; rnp_result_t ret = RNP_ERROR_GENERIC; if (param->cleartext) { @@ -988,7 +1050,7 @@ ret = signed_read_signatures(src); } - if (ret != RNP_SUCCESS) { + if (ret) { return ret; } @@ -997,38 +1059,11 @@ } /* validating signatures */ - keyctx.op = PGP_OP_VERIFY; - keyctx.search.type = PGP_KEY_SEARCH_KEYID; - for (auto &sinfo : param->siginfos) { if (!sinfo.sig) { continue; } - - /* we need public key, however may fallback to secret later on */ - keyctx.secret = false; - - /* Get the key id */ - if (!sinfo.sig->has_keyid()) { - RNP_LOG("cannot get signer's key id from signature"); - sinfo.unknown = true; - continue; - } - keyctx.search.by.keyid = sinfo.sig->keyid(); - - /* Get the public key */ - if (!(key = pgp_request_key(param->handler->key_provider, &keyctx))) { - // fallback to secret key - keyctx.secret = true; - if (!(key = pgp_request_key(param->handler->key_provider, &keyctx))) { - RNP_LOG("signer's key not found"); - sinfo.no_signer = true; - continue; - } - } - sinfo.signer = key; - /* validate signature */ - signed_validate_signature(param, &sinfo); + signed_validate_signature(*param, sinfo); } /* checking the validation results */ @@ -1098,29 +1133,35 @@ break; } - if (rnp_is_blank_line(hdr, hdrlen)) { + if (rnp::is_blank_line(hdr, hdrlen)) { src_skip(param->readsrc, hdrlen); break; } - if ((hdrlen >= 6) && !strncmp(hdr, ST_HEADER_HASH, 6)) { - hval = hdr + 6; - - std::string remainder = hval; + try { + if ((hdrlen >= 6) && !strncmp(hdr, ST_HEADER_HASH, 6)) { + hval = hdr + 6; - const std::string delimiters = ", \t"; - std::vector tokens; + std::string remainder = hval; - tokenize(remainder, delimiters, tokens); + const std::string delimiters = ", \t"; + std::vector tokens; - for (const auto &token : tokens) { - if ((halg = pgp_str_to_hash_alg(token.c_str())) == PGP_HASH_UNKNOWN) { - RNP_LOG("unknown halg: %s", token.c_str()); + tokenize(remainder, delimiters, tokens); + + for (const auto &token : tokens) { + if ((halg = rnp::Hash::alg(token.c_str())) == PGP_HASH_UNKNOWN) { + RNP_LOG("unknown halg: %s", token.c_str()); + continue; + } + add_hash_for_sig(param, PGP_SIG_TEXT, halg); } - add_hash_for_sig(param, PGP_SIG_TEXT, halg); + } else { + RNP_LOG("unknown header '%s'", hdr); } - } else { - RNP_LOG("unknown header '%s'", hdr); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return false; } src_skip(param->readsrc, hdrlen); @@ -1247,8 +1288,8 @@ /* if line is larger then 4k then just dump it out */ if ((bg == srcb) && !param->clr_eod) { - /* if last char is \r then do not dump it */ - if ((en > bg) && (*(en - 1) == CH_CR)) { + /* if last char is \r, and it's not the end of stream, then do not dump it */ + if ((en > bg) && (*(en - 1) == CH_CR) && (read > 1)) { en--; } cleartext_process_line(src, bg, en - bg, false); @@ -1323,14 +1364,14 @@ return true; } - if (!pgp_hash_create(¶m->mdc, PGP_HASH_SHA1)) { - RNP_LOG("cannot create sha1 hash"); + try { + param->mdc = rnp::Hash(PGP_HASH_SHA1); + param->mdc.add(dechdr, blsize + 2); + } catch (const std::exception &e) { + RNP_LOG("cannot create sha1 hash: %s", e.what()); goto error; } - - pgp_hash_add(¶m->mdc, dechdr, blsize + 2); return true; - error: pgp_cipher_cfb_finish(&crypt); return false; @@ -1339,6 +1380,10 @@ static bool encrypted_start_aead(pgp_source_encrypted_param_t *param, pgp_symm_alg_t alg, uint8_t *key) { +#if !defined(ENABLE_AEAD) + RNP_LOG("AEAD is not enabled."); + return false; +#else size_t gran; if (alg != param->aead_hdr.ealg) { @@ -1358,19 +1403,25 @@ } return encrypted_start_aead_chunk(param, 0, false); +#endif } static bool encrypted_try_key(pgp_source_encrypted_param_t *param, pgp_pk_sesskey_t * sesskey, pgp_key_pkt_t * seckey, - rng_t * rng) + rnp::SecurityContext & ctx) { pgp_encrypted_material_t encmaterial; try { if (!sesskey->parse_material(encmaterial)) { return false; } + seckey->material.validate(ctx, false); + if (!seckey->material.valid()) { + RNP_LOG("Attempt to decrypt using the key with invalid material."); + return false; + } } catch (const std::exception &e) { RNP_LOG("%s", e.what()); return false; @@ -1385,14 +1436,15 @@ switch (sesskey->alg) { case PGP_PKA_RSA: case PGP_PKA_RSA_ENCRYPT_ONLY: - err = - rsa_decrypt_pkcs1(rng, decbuf.data(), &declen, &encmaterial.rsa, &keymaterial->rsa); + err = rsa_decrypt_pkcs1( + &ctx.rng, decbuf.data(), &declen, &encmaterial.rsa, &keymaterial->rsa); if (err) { RNP_LOG("RSA decryption failure"); return false; } break; case PGP_PKA_SM2: +#if defined(ENABLE_SM2) declen = decbuf.size(); err = sm2_decrypt(decbuf.data(), &declen, &encmaterial.sm2, &keymaterial->ec); if (err != RNP_SUCCESS) { @@ -1400,10 +1452,14 @@ return false; } break; +#else + RNP_LOG("SM2 decryption is not available."); + return false; +#endif case PGP_PKA_ELGAMAL: case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: { const rnp_result_t ret = elgamal_decrypt_pkcs1( - rng, decbuf.data(), &declen, &encmaterial.eg, &keymaterial->eg); + &ctx.rng, decbuf.data(), &declen, &encmaterial.eg, &keymaterial->eg); if (ret) { RNP_LOG("ElGamal decryption failure [%X]", ret); return false; @@ -1411,11 +1467,18 @@ break; } case PGP_PKA_ECDH: { + if (!curve_supported(keymaterial->ec.curve)) { + RNP_LOG("ECDH decrypt: curve %d is not supported.", (int) keymaterial->ec.curve); + return false; + } pgp_fingerprint_t fingerprint; if (pgp_fingerprint(fingerprint, *seckey)) { RNP_LOG("ECDH fingerprint calculation failed"); return false; } + if (!x25519_bits_tweaked(keymaterial->ec)) { + RNP_LOG("Warning: bits of 25519 secret key are not tweaked."); + } declen = decbuf.size(); err = ecdh_decrypt_pkcs5( decbuf.data(), &declen, &encmaterial.ecdh, &keymaterial->ec, fingerprint); @@ -1468,6 +1531,7 @@ return res; } +#if defined(ENABLE_AEAD) static bool encrypted_sesk_set_ad(pgp_crypt_t *crypt, pgp_sk_sesskey_t *skey) { @@ -1479,9 +1543,9 @@ ad_data[2] = skey->alg; ad_data[3] = skey->aalg; - RNP_DHEX("sesk ad: ", ad_data, 4); return pgp_cipher_aead_set_ad(crypt, ad_data, 4); } +#endif static int encrypted_try_password(pgp_source_encrypted_param_t *param, const char *password) @@ -1495,7 +1559,6 @@ if (!keysize || !pgp_s2k_derive_key(&skey.s2k, password, keybuf.data(), keysize)) { continue; } - RNP_DHEX("derived key: ", keybuf.data(), keysize); pgp_crypt_t crypt; pgp_symm_alg_t alg; @@ -1525,6 +1588,9 @@ } keyavail = true; } else if (skey.version == PGP_SKSK_V5) { +#if !defined(ENABLE_AEAD) + continue; +#else /* v5 AEAD-encrypted session key */ size_t taglen = pgp_cipher_aead_tag_len(skey.aalg); uint8_t nonce[PGP_AEAD_MAX_NONCE_LEN]; @@ -1549,24 +1615,18 @@ /* calculate nonce */ noncelen = pgp_cipher_aead_nonce(skey.aalg, skey.iv, nonce, 0); - RNP_DHEX("nonce: ", nonce, noncelen); - RNP_DHEX("encrypted key: ", skey.enckey, skey.enckeylen); - /* start cipher, decrypt key and verify tag */ keyavail = pgp_cipher_aead_start(&crypt, nonce, noncelen); bool decres = keyavail && pgp_cipher_aead_finish( &crypt, keybuf.data(), skey.enckey, skey.enckeylen); - if (decres) { - RNP_DHEX("decrypted key: ", keybuf.data(), pgp_key_size(param->aead_hdr.ealg)); - } - pgp_cipher_aead_destroy(&crypt); /* we have decrypted key so let's start decryption */ if (!keyavail || !decres) { continue; } +#endif } else { continue; } @@ -1587,6 +1647,11 @@ return 1; } + if (param->aead && pgp_block_size(param->aead_hdr.ealg)) { + /* we know aead symm alg even if we wasn't able to start decryption */ + param->salg = param->aead_hdr.ealg; + } + if (!keyavail) { RNP_LOG("no supported sk available"); return -1; @@ -1698,9 +1763,7 @@ ret = RNP_ERROR_READ; goto finish; } - - param->hdr.timestamp = ((uint32_t) tstbuf[0] << 24) | ((uint32_t) tstbuf[1] << 16) | - ((uint32_t) tstbuf[2] << 8) | (uint32_t) tstbuf[3]; + param->hdr.timestamp = read_uint32(tstbuf); if (!param->pkt.indeterminate && !param->pkt.partial) { /* format filename-length filename timestamp */ @@ -1769,6 +1832,8 @@ /* Initializing decompression */ switch (alg) { + case PGP_C_NONE: + break; case PGP_C_ZIP: case PGP_C_ZLIB: (void) memset(¶m->z, 0x0, sizeof(param->z)); @@ -1845,6 +1910,8 @@ return src_read_eq(src, hdr->iv, hdr->ivlen); } +#define MAX_RECIPIENTS 16384 + static rnp_result_t encrypted_read_packet_data(pgp_source_encrypted_param_t *param) { @@ -1853,6 +1920,10 @@ try { bool stop = false; while (!stop) { + if (param->pubencs.size() + param->symencs.size() > MAX_RECIPIENTS) { + RNP_LOG("Too many recipients of the encrypted message. Aborting."); + return RNP_ERROR_BAD_STATE; + } uint8_t ptag; if (!src_peek_eq(param->pkt.readsrc, &ptag, 1)) { RNP_LOG("failed to read packet header"); @@ -2025,7 +2096,7 @@ if (seckey->encrypted()) { pgp_password_ctx_t pass_ctx{.op = PGP_OP_DECRYPT, .key = seckey}; decrypted_seckey = - pgp_decrypt_seckey(seckey, handler->password_provider, &pass_ctx); + pgp_decrypt_seckey(*seckey, *handler->password_provider, pass_ctx); if (!decrypted_seckey) { errcode = RNP_ERROR_BAD_PASSWORD; continue; @@ -2035,8 +2106,7 @@ } /* Try to initialize the decryption */ - if (encrypted_try_key( - param, &pubenc, decrypted_seckey, rnp_ctx_rng_handle(handler->ctx))) { + if (encrypted_try_key(param, &pubenc, decrypted_seckey, *handler->ctx->ctx)) { have_key = true; /* inform handler that we used this pubenc */ if (handler->on_decryption_start) { @@ -2076,6 +2146,12 @@ } } + /* report decryption start to the handler */ + if (handler->on_decryption_info) { + handler->on_decryption_info( + param->has_mdc, param->aead_hdr.aalg, param->salg, handler->param); + } + if (!have_key) { RNP_LOG("failed to obtain decrypting key or password"); if (!errcode) { @@ -2083,12 +2159,6 @@ } goto finish; } - - /* report decryption start to the handler */ - if (handler->on_decryption_info) { - handler->on_decryption_info( - param->has_mdc, param->aead_hdr.aalg, param->salg, handler->param); - } errcode = RNP_SUCCESS; finish: if (errcode != RNP_SUCCESS) { @@ -2131,16 +2201,6 @@ return RNP_SUCCESS; } -pgp_source_signed_param_t::~pgp_source_signed_param_t() -{ - for (auto &hash : hashes) { - pgp_hash_finish(&hash, NULL); - } - for (auto &hash : txt_hashes) { - pgp_hash_finish(&hash, NULL); - } -} - #define MAX_SIG_ERRORS 65536 static rnp_result_t @@ -2206,6 +2266,11 @@ ptype = get_packet_type(ptag); if (ptype == PGP_PKT_ONE_PASS_SIG) { + if (param->onepasses.size() >= MAX_SIGNATURES) { + RNP_LOG("Too many one-pass signatures."); + errcode = RNP_ERROR_BAD_FORMAT; + goto finish; + } pgp_one_pass_sig_t onepass; try { errcode = onepass.parse(*readsrc); @@ -2233,10 +2298,13 @@ } /* adding hash context */ - if (!add_hash_for_sig(param, onepass.type, onepass.halg)) { - RNP_LOG("Failed to create hash %d for onepass %d.", + try { + add_hash_for_sig(param, onepass.type, onepass.halg); + } catch (const std::exception &e) { + RNP_LOG("Failed to create hash %d for onepass %d : %s.", (int) onepass.halg, - (int) onepass.type); + (int) onepass.type, + e.what()); errcode = RNP_ERROR_BAD_PARAMETERS; goto finish; } @@ -2251,11 +2319,17 @@ sigerrors++; } /* adding hash context */ - if (sig && !add_hash_for_sig(param, sig->type(), sig->halg)) { - RNP_LOG( - "Failed to create hash %d for sig %d.", (int) sig->halg, (int) sig->type()); - errcode = RNP_ERROR_BAD_PARAMETERS; - goto finish; + if (sig) { + try { + add_hash_for_sig(param, sig->type(), sig->halg); + } catch (const std::exception &e) { + RNP_LOG("Failed to create hash %d for sig %d : %s.", + (int) sig->halg, + (int) sig->type(), + e.what()); + errcode = RNP_ERROR_BAD_PARAMETERS; + goto finish; + } } } else { break; @@ -2443,7 +2517,6 @@ pgp_dest_t * outdest = NULL; bool closeout = true; uint8_t * readbuf = NULL; - char * filename = NULL; ctx.handler = *handler; /* Building readers sequence. Checking whether it is binary data */ @@ -2506,12 +2579,17 @@ } /* file processing case */ decsrc = &ctx.sources.back(); + char * filename = NULL; + uint32_t mtime = 0; + if (ctx.literal_src) { - filename = ((pgp_source_literal_param_t *) ctx.literal_src)->hdr.fname; + auto *param = static_cast(ctx.literal_src->param); + filename = param->hdr.fname; + mtime = param->hdr.timestamp; } if (!handler->dest_provider || - !handler->dest_provider(handler, &outdest, &closeout, filename)) { + !handler->dest_provider(handler, &outdest, &closeout, filename, mtime)) { res = RNP_ERROR_WRITE; goto finish; } @@ -2540,8 +2618,8 @@ /* finalizing the input. Signatures are checked on this step */ if (res == RNP_SUCCESS) { - for (auto &src : ctx.sources) { - fres = src_finish(&src); + for (auto &ctxsrc : ctx.sources) { + fres = src_finish(&ctxsrc); if (fres) { res = fres; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-parse.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-parse.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-parse.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-parse.h 2022-04-15 07:49:22.000000000 +0000 @@ -40,7 +40,8 @@ typedef bool pgp_destination_func_t(pgp_parse_handler_t *handler, pgp_dest_t ** dst, bool * closedst, - const char * filename); + const char * filename, + uint32_t mtime); typedef bool pgp_source_func_t(pgp_parse_handler_t *handler, pgp_source_t *src); typedef void pgp_signatures_func_t(const std::vector &sigs, void *param); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-sig.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-sig.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-sig.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-sig.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -45,166 +45,33 @@ #include -bool -signature_set_embedded_sig(pgp_signature_t *sig, pgp_signature_t *esig) -{ - pgp_sig_subpkt_t *subpkt = NULL; - pgp_dest_t memdst = {}; - pgp_source_t memsrc = {}; - size_t len = 0; - bool res = false; - - if (init_mem_dest(&memdst, NULL, 0)) { - RNP_LOG("alloc failed"); - return false; - } - try { - esig->write(memdst); - } catch (const std::exception &e) { - RNP_LOG("failed to write signature: %s", e.what()); - goto finish; - } - if (init_mem_src(&memsrc, mem_dest_get_memory(&memdst), memdst.writeb, false)) { - RNP_LOG("failed to init mem src"); - goto finish; - } - if (!stream_read_pkt_len(&memsrc, &len)) { - RNP_LOG("wrong pkt len"); - goto finish; - } - - try { - subpkt = &sig->add_subpkt(PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE, len, true); - subpkt->hashed = false; - if (!src_read_eq(&memsrc, subpkt->data, len)) { - RNP_LOG("failed to read back signature"); - goto finish; - } - subpkt->fields.sig = new pgp_signature_t(*esig); - subpkt->parsed = true; - res = true; - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - } -finish: - if (!res && subpkt) { - sig->remove_subpkt(subpkt); - } - src_close(&memsrc); - dst_close(&memdst, true); - return res; -} - -bool -signature_add_notation_data(pgp_signature_t *sig, - bool readable, - const char * name, - const char * value) -{ - size_t nlen = strlen(name); - size_t vlen = strlen(value); - - if ((nlen > 0xffff) || (vlen > 0xffff)) { - RNP_LOG("wrong length"); - return false; - } - - try { - pgp_sig_subpkt_t &subpkt = - sig->add_subpkt(PGP_SIG_SUBPKT_NOTATION_DATA, 8 + nlen + vlen, false); - subpkt.hashed = true; - if (readable) { - subpkt.data[0] = 0x80; - subpkt.fields.notation.flags[0] = 0x80; - } - write_uint16(subpkt.data + 4, nlen); - memcpy(subpkt.data + 6, name, nlen); - write_uint16(subpkt.data + 6 + nlen, vlen); - memcpy(subpkt.data + 8 + nlen, value, vlen); - return subpkt.parse(); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return false; - } -} - -bool -signature_fill_hashed_data(pgp_signature_t *sig) -{ - /* we don't have a need to write v2-v3 signatures */ - if ((sig->version < PGP_V2) || (sig->version > PGP_V4)) { - RNP_LOG("don't know version %d", (int) sig->version); - return false; - } - try { - pgp_packet_body_t hbody(PGP_PKT_RESERVED); - if (sig->version < PGP_V4) { - hbody.add_byte(sig->type()); - hbody.add_uint32(sig->creation_time); - } else { - hbody.add_byte(sig->version); - hbody.add_byte(sig->type()); - hbody.add_byte(sig->palg); - hbody.add_byte(sig->halg); - hbody.add_subpackets(*sig, true); - } - - free(sig->hashed_data); - sig->hashed_data = (uint8_t *) malloc(hbody.size()); - if (!sig->hashed_data) { - RNP_LOG("allocation failed"); - return false; - } - memcpy(sig->hashed_data, hbody.data(), hbody.size()); - sig->hashed_len = hbody.size(); - return true; - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return false; - } -} - -bool -signature_hash_key(const pgp_key_pkt_t *key, pgp_hash_t *hash) +void +signature_hash_key(const pgp_key_pkt_t &key, rnp::Hash &hash) { - if (!key || !hash) { - RNP_LOG("null key or hash"); - return false; - } - uint8_t hdr[3] = {0x99, 0x00, 0x00}; - if (key->hashed_data) { - write_uint16(hdr + 1, key->hashed_len); - return !pgp_hash_add(hash, hdr, 3) && - !pgp_hash_add(hash, key->hashed_data, key->hashed_len); + if (key.hashed_data) { + write_uint16(hdr + 1, key.hashed_len); + hash.add(hdr, 3); + hash.add(key.hashed_data, key.hashed_len); + return; } /* call self recursively if hashed data is not filled, to overcome const restriction */ - try { - pgp_key_pkt_t keycp(*key, true); - keycp.fill_hashed_data(); - return signature_hash_key(&keycp, hash); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return false; - } + pgp_key_pkt_t keycp(key, true); + keycp.fill_hashed_data(); + signature_hash_key(keycp, hash); } -bool -signature_hash_userid(const pgp_userid_pkt_t *uid, pgp_hash_t *hash, pgp_version_t sigver) +void +signature_hash_userid(const pgp_userid_pkt_t &uid, rnp::Hash &hash, pgp_version_t sigver) { - uint8_t hdr[5] = {0}; - - if (!uid || !hash) { - RNP_LOG("null uid or hash"); - return false; - } - if (sigver < PGP_V4) { - return !pgp_hash_add(hash, uid->uid, uid->uid_len); + hash.add(uid.uid, uid.uid_len); + return; } - switch (uid->tag) { + uint8_t hdr[5] = {0}; + switch (uid.tag) { case PGP_PKT_USER_ID: hdr[0] = 0xB4; break; @@ -213,257 +80,40 @@ break; default: RNP_LOG("wrong uid"); - return false; - } - STORE32BE(hdr + 1, uid->uid_len); - - return !pgp_hash_add(hash, hdr, 5) && !pgp_hash_add(hash, uid->uid, uid->uid_len); -} - -bool -signature_hash_signature(pgp_signature_t *sig, pgp_hash_t *hash) -{ - uint8_t hdr[5] = {0x88, 0x00, 0x00, 0x00, 0x00}; - - if (!sig || !hash) { - RNP_LOG("null sig or hash"); - return false; - } - - if (!sig->hashed_data) { - RNP_LOG("hashed data not filled"); - return false; - } - - STORE32BE(hdr + 1, sig->hashed_len); - return !pgp_hash_add(hash, hdr, 5) && - !pgp_hash_add(hash, sig->hashed_data, sig->hashed_len); -} - -bool -signature_hash_certification(const pgp_signature_t * sig, - const pgp_key_pkt_t * key, - const pgp_userid_pkt_t *userid, - pgp_hash_t * hash) -{ - bool res = false; - - if (signature_init(&key->material, sig->halg, hash) != RNP_SUCCESS) { - return false; - } - - res = signature_hash_key(key, hash) && signature_hash_userid(userid, hash, sig->version); - - if (!res) { - pgp_hash_finish(hash, NULL); - } - - return res; -} - -bool -signature_hash_binding(const pgp_signature_t *sig, - const pgp_key_pkt_t * key, - const pgp_key_pkt_t * subkey, - pgp_hash_t * hash) -{ - bool res = false; - - if (signature_init(&key->material, sig->halg, hash) != RNP_SUCCESS) { - return false; - } - - res = signature_hash_key(key, hash) && signature_hash_key(subkey, hash); - - if (!res) { - pgp_hash_finish(hash, NULL); - } - - return res; -} - -bool -signature_hash_direct(const pgp_signature_t *sig, const pgp_key_pkt_t *key, pgp_hash_t *hash) -{ - bool res = false; - - if (signature_init(&key->material, sig->halg, hash) != RNP_SUCCESS) { - return false; - } - - res = signature_hash_key(key, hash); - - if (!res) { - pgp_hash_finish(hash, NULL); - } - - return res; -} - -rnp_result_t -signature_check(pgp_signature_info_t *sinfo, pgp_hash_t *hash) -{ - uint32_t now; - uint32_t create, expiry, kcreate; - rnp_result_t ret = RNP_ERROR_SIGNATURE_INVALID; - - sinfo->no_signer = !sinfo->signer; - sinfo->valid = false; - sinfo->expired = false; - - if (!sinfo->sig) { - ret = RNP_ERROR_NULL_POINTER; - goto finish; - } - - if (!sinfo->signer) { - ret = RNP_ERROR_NO_SUITABLE_KEY; - goto finish; - } - - /* Validate signature itself */ - if (sinfo->signer_valid || sinfo->signer->valid_at(sinfo->sig->creation())) { - sinfo->valid = !signature_validate(sinfo->sig, &sinfo->signer->material(), hash); - } else { - sinfo->valid = false; - RNP_LOG("invalid or untrusted key"); - } - - /* Check signature's expiration time */ - now = time(NULL); - create = sinfo->sig->creation(); - expiry = sinfo->sig->expiration(); - if (create > now) { - /* signature created later then now */ - RNP_LOG("signature created %d seconds in future", (int) (create - now)); - sinfo->expired = true; - } - if (create && expiry && (create + expiry < now)) { - /* signature expired */ - RNP_LOG("signature expired"); - sinfo->expired = true; - } - - /* check key creation time vs signature creation */ - kcreate = sinfo->signer->creation(); - if (kcreate > create) { - RNP_LOG("key is newer than signature"); - sinfo->valid = false; - } - - /* check whether key was not expired when sig created */ - if (!sinfo->ignore_expiry && sinfo->signer->expiration() && - (kcreate + sinfo->signer->expiration() < create)) { - RNP_LOG("signature made after key expiration"); - sinfo->valid = false; - } - - /* Check signer's fingerprint */ - if (sinfo->sig->has_keyfp() && (sinfo->sig->keyfp() != sinfo->signer->fp())) { - RNP_LOG("issuer fingerprint doesn't match signer's one"); - sinfo->valid = false; - } - - if (sinfo->expired && sinfo->valid) { - ret = RNP_ERROR_SIGNATURE_EXPIRED; - } else { - ret = sinfo->valid ? RNP_SUCCESS : RNP_ERROR_SIGNATURE_INVALID; - } -finish: - pgp_hash_finish(hash, NULL); - return ret; -} - -rnp_result_t -signature_check_certification(pgp_signature_info_t * sinfo, - const pgp_key_pkt_t * key, - const pgp_userid_pkt_t *uid) -{ - pgp_hash_t hash = {}; - - if (!signature_hash_certification(sinfo->sig, key, uid, &hash)) { - return RNP_ERROR_BAD_FORMAT; + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } - - return signature_check(sinfo, &hash); + STORE32BE(hdr + 1, uid.uid_len); + hash.add(hdr, 5); + hash.add(uid.uid, uid.uid_len); } -rnp_result_t -signature_check_binding(pgp_signature_info_t *sinfo, - const pgp_key_pkt_t * key, - const pgp_key_t * subkey) +void +signature_hash_certification(const pgp_signature_t & sig, + const pgp_key_pkt_t & key, + const pgp_userid_pkt_t &userid, + rnp::Hash & hash) { - pgp_hash_t hash = {}; - rnp_result_t res = RNP_ERROR_SIGNATURE_INVALID; - - if (!signature_hash_binding(sinfo->sig, key, &subkey->pkt(), &hash)) { - return RNP_ERROR_BAD_FORMAT; - } - - res = signature_check(sinfo, &hash); - if (res || !(sinfo->sig->key_flags() & PGP_KF_SIGN)) { - return res; - } - - /* check primary key binding signature if any */ - res = RNP_ERROR_SIGNATURE_INVALID; - sinfo->valid = false; - pgp_sig_subpkt_t *subpkt = - sinfo->sig->get_subpkt(PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE, false); - if (!subpkt) { - RNP_LOG("error! no primary key binding signature"); - return res; - } - if (!subpkt->parsed) { - RNP_LOG("invalid embedded signature subpacket"); - return res; - } - if (subpkt->fields.sig->type() != PGP_SIG_PRIMARY) { - RNP_LOG("invalid primary key binding signature"); - return res; - } - if (subpkt->fields.sig->version < PGP_V4) { - RNP_LOG("invalid primary key binding signature version"); - return res; - } - - if (!signature_hash_binding(subpkt->fields.sig, key, &subkey->pkt(), &hash)) { - return RNP_ERROR_BAD_FORMAT; - } - pgp_signature_info_t bindinfo = {}; - bindinfo.sig = subpkt->fields.sig; - bindinfo.signer = subkey; - bindinfo.signer_valid = true; - bindinfo.ignore_expiry = true; - res = signature_check(&bindinfo, &hash); - sinfo->valid = !res; - return res; + signature_init(key.material, sig.halg, hash); + signature_hash_key(key, hash); + signature_hash_userid(userid, hash, sig.version); } -rnp_result_t -signature_check_direct(pgp_signature_info_t *sinfo, const pgp_key_pkt_t *key) +void +signature_hash_binding(const pgp_signature_t &sig, + const pgp_key_pkt_t & key, + const pgp_key_pkt_t & subkey, + rnp::Hash & hash) { - pgp_hash_t hash = {}; - - if (!signature_hash_direct(sinfo->sig, key, &hash)) { - return RNP_ERROR_BAD_FORMAT; - } - - return signature_check(sinfo, &hash); + signature_init(key.material, sig.halg, hash); + signature_hash_key(key, hash); + signature_hash_key(subkey, hash); } -rnp_result_t -signature_check_subkey_revocation(pgp_signature_info_t *sinfo, - const pgp_key_pkt_t * key, - const pgp_key_pkt_t * subkey) +void +signature_hash_direct(const pgp_signature_t &sig, const pgp_key_pkt_t &key, rnp::Hash &hash) { - pgp_hash_t hash = {}; - - if (!signature_hash_binding(sinfo->sig, key, subkey, &hash)) { - return RNP_ERROR_BAD_FORMAT; - } - - return signature_check(sinfo, &hash); + signature_init(key.material, sig.halg, hash); + signature_hash_key(key, hash); } rnp_result_t @@ -667,14 +317,14 @@ case PGP_SIG_SUBPKT_NOTATION_DATA: if ((oklen = len >= 8)) { memcpy(fields.notation.flags, data, 4); + fields.notation.human = fields.notation.flags[0] & 0x80; fields.notation.nlen = read_uint16(&data[4]); fields.notation.vlen = read_uint16(&data[6]); - if (len != 8 + fields.notation.nlen + fields.notation.vlen) { oklen = false; } else { - fields.notation.name = (const char *) &data[8]; - fields.notation.value = (const char *) &data[8 + fields.notation.nlen]; + fields.notation.name = data + 8; + fields.notation.value = fields.notation.name + fields.notation.nlen; } } break; @@ -935,18 +585,13 @@ pgp_sig_id_t pgp_signature_t::get_id() const { - pgp_hash_t hash = {}; - if (!pgp_hash_create(&hash, PGP_HASH_SHA1)) { - RNP_LOG("bad sha1 alloc"); - throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); - } - - pgp_hash_add(&hash, hashed_data, hashed_len); - pgp_hash_add(&hash, material_buf, material_len); + rnp::Hash hash(PGP_HASH_SHA1); + hash.add(hashed_data, hashed_len); + hash.add(material_buf, material_len); pgp_sig_id_t res; static_assert(std::tuple_size::value == PGP_SHA1_HASH_SIZE, "pgp_sig_id_t size mismatch"); - pgp_hash_finish(&hash, res.data()); + hash.finish(res.data()); return res; } @@ -1003,7 +648,7 @@ } pgp_key_id_t -pgp_signature_t::keyid() const +pgp_signature_t::keyid() const noexcept { /* version 3 uses signature field */ if (version < PGP_V4) { @@ -1011,7 +656,7 @@ } /* version 4 and up use subpackets */ - pgp_key_id_t res; + pgp_key_id_t res{}; static_assert(std::tuple_size::value == PGP_KEY_ID_SIZE, "pgp_key_id_t size mismatch"); @@ -1026,7 +671,7 @@ PGP_KEY_ID_SIZE); return res; } - throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + return res; } void @@ -1058,15 +703,15 @@ } pgp_fingerprint_t -pgp_signature_t::keyfp() const +pgp_signature_t::keyfp() const noexcept { + pgp_fingerprint_t res{}; if (version < PGP_V4) { - throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + return res; } const pgp_sig_subpkt_t *subpkt = get_subpkt(PGP_SIG_SUBPKT_ISSUER_FPR); - pgp_fingerprint_t res; if (!subpkt || (subpkt->fields.issuer_fp.len > sizeof(res.fingerprint))) { - throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + return res; } res.length = subpkt->fields.issuer_fp.len; memcpy(res.fingerprint, subpkt->fields.issuer_fp.fp, subpkt->fields.issuer_fp.len); @@ -1418,6 +1063,64 @@ subpkt.parsed = true; } +void +pgp_signature_t::add_notation(const std::string & name, + const std::vector &value, + bool human, + bool critical) +{ + auto nlen = name.size(); + auto vlen = value.size(); + if ((nlen > 0xffff) || (vlen > 0xffff)) { + RNP_LOG("wrong length"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + + auto &subpkt = add_subpkt(PGP_SIG_SUBPKT_NOTATION_DATA, 8 + nlen + vlen, false); + subpkt.hashed = true; + subpkt.critical = critical; + if (human) { + subpkt.data[0] = 0x80; + } + write_uint16(subpkt.data + 4, nlen); + write_uint16(subpkt.data + 6, vlen); + memcpy(subpkt.data + 8, name.data(), nlen); + memcpy(subpkt.data + 8 + nlen, value.data(), vlen); + if (!subpkt.parse()) { + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } +} + +void +pgp_signature_t::add_notation(const std::string &name, const std::string &value, bool critical) +{ + add_notation(name, std::vector(value.begin(), value.end()), true, critical); +} + +void +pgp_signature_t::set_embedded_sig(const pgp_signature_t &esig) +{ + pgp_rawpacket_t esigpkt(esig); + pgp_source_t memsrc = {}; + if (init_mem_src(&memsrc, esigpkt.raw.data(), esigpkt.raw.size(), false)) { + RNP_LOG("failed to init mem src"); + throw rnp::rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + size_t len = 0; + stream_read_pkt_len(&memsrc, &len); + src_close(&memsrc); + if (!len || (len > 0xffff) || (len >= esigpkt.raw.size())) { + RNP_LOG("wrong pkt len"); + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); + } + pgp_sig_subpkt_t &subpkt = add_subpkt(PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE, len, true); + subpkt.hashed = false; + size_t skip = esigpkt.raw.size() - len; + memcpy(subpkt.data, esigpkt.raw.data() + skip, len); + subpkt.fields.sig = new pgp_signature_t(esig); + subpkt.parsed = true; +} + pgp_sig_subpkt_t & pgp_signature_t::add_subpkt(pgp_sig_subpacket_type_t type, size_t datalen, bool reuse) { @@ -1504,12 +1207,18 @@ return RNP_SUCCESS; } +#define MAX_SUBPACKETS 64 + bool pgp_signature_t::parse_subpackets(uint8_t *buf, size_t len, bool hashed) { bool res = true; while (len > 0) { + if (subpkts.size() >= MAX_SUBPACKETS) { + RNP_LOG("too many signature subpackets"); + return false; + } if (len < 2) { RNP_LOG("got single byte %d", (int) *buf); return false; @@ -1536,8 +1245,8 @@ } if (splen < 1) { - RNP_LOG("got subpacket with 0 length, skipping"); - continue; + RNP_LOG("got subpacket with 0 length"); + return false; } /* subpacket data */ @@ -1712,7 +1421,7 @@ if (version < PGP_V4) { RNP_LOG("Warning! v3 EdDSA signature."); } - /* FALLTHROUGH */ + [[fallthrough]]; case PGP_PKA_ECDSA: case PGP_PKA_SM2: case PGP_PKA_ECDH: @@ -1805,3 +1514,72 @@ memcpy(material_buf, pktbody.data(), pktbody.size()); material_len = pktbody.size(); } + +void +pgp_signature_t::fill_hashed_data() +{ + /* we don't have a need to write v2-v3 signatures */ + if ((version < PGP_V2) || (version > PGP_V4)) { + RNP_LOG("don't know version %d", (int) version); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + pgp_packet_body_t hbody(PGP_PKT_RESERVED); + if (version < PGP_V4) { + hbody.add_byte(type()); + hbody.add_uint32(creation_time); + } else { + hbody.add_byte(version); + hbody.add_byte(type()); + hbody.add_byte(palg); + hbody.add_byte(halg); + hbody.add_subpackets(*this, true); + } + + free(hashed_data); + hashed_data = (uint8_t *) malloc(hbody.size()); + if (!hashed_data) { + RNP_LOG("allocation failed"); + throw std::bad_alloc(); + } + memcpy(hashed_data, hbody.data(), hbody.size()); + hashed_len = hbody.size(); +} + +void +rnp_selfsig_cert_info_t::populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig) +{ + /* populate signature */ + sig.set_type(PGP_CERT_POSITIVE); + if (key_expiration) { + sig.set_key_expiration(key_expiration); + } + if (key_flags) { + sig.set_key_flags(key_flags); + } + if (primary) { + sig.set_primary_uid(true); + } + if (!prefs.symm_algs.empty()) { + sig.set_preferred_symm_algs(prefs.symm_algs); + } + if (!prefs.hash_algs.empty()) { + sig.set_preferred_hash_algs(prefs.hash_algs); + } + if (!prefs.z_algs.empty()) { + sig.set_preferred_z_algs(prefs.z_algs); + } + if (!prefs.ks_prefs.empty()) { + sig.set_key_server_prefs(prefs.ks_prefs[0]); + } + if (!prefs.key_server.empty()) { + sig.set_key_server(prefs.key_server); + } + /* populate uid */ + uid.tag = PGP_PKT_USER_ID; + uid.uid_len = strlen((char *) userid); + if (!(uid.uid = (uint8_t *) malloc(uid.uid_len))) { + RNP_LOG("alloc failed"); + throw rnp::rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + memcpy(uid.uid, (char *) userid, uid.uid_len); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-sig.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-sig.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-sig.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-sig.h 2022-04-15 07:49:22.000000000 +0000 @@ -105,9 +105,9 @@ bool has_keyid() const; /** * @brief Get signer's key id if available. Availability may be checked via has_keyid(). - * @return signer's key id if available, or throws an exception otherwise. + * @return signer's key id if available, or empty (zero-filled) keyid otherwise. */ - pgp_key_id_t keyid() const; + pgp_key_id_t keyid() const noexcept; /** @brief Set the signer's key id for the signature being populated. Version should be set * prior of setting key id. */ void set_keyid(const pgp_key_id_t &id); @@ -120,9 +120,9 @@ /** * @brief Get signing key's fingerprint if it is available. Availability may be checked via * has_keyfp() method. - * @return fingerprint or throws an error if it is unavailable. + * @return fingerprint (or empty zero-size fp in case it is unavailable) */ - pgp_fingerprint_t keyfp() const; + pgp_fingerprint_t keyfp() const noexcept; /** @brief Set signing key's fingerprint. Works only for signatures with version 4 and up, * so version should be set prior to fingerprint. */ @@ -253,7 +253,7 @@ void set_revocable(bool status); /** @brief Get the key/subkey revocation reason in humand-readable form. If there is no - * revocation reason subpacket, then empty string will be returned. + * revocation reason subpacket, then empty string will be returned. */ std::string revocation_reason() const; @@ -270,17 +270,17 @@ /** * @brief Check whether signer's key supports certain feature(s). Makes sense only for - * self-signature, for more details see the RFC 4880bis, 5.2.3.25. If there is no - * corresponding subpacket then false will be returned. + * self-signature, for more details see the RFC 4880bis, 5.2.3.25. If there is + * no corresponding subpacket then false will be returned. * @param flags one or more flags, combined via bitwise OR operation. * @return true if key is claimed to support all of the features listed in flags, or false - * otherwise + * otherwise */ bool key_has_features(pgp_key_feature_t flags) const; /** * @brief Set the features supported by the signer's key, makes sense only for - * self-signature. For more details see the RFC 4880bis, 5.2.3.25. + * self-signature. For more details see the RFC 4880bis, 5.2.3.25. * @param flags one or more flags, combined via bitwise OR operation. */ void set_key_features(pgp_key_feature_t flags); @@ -292,11 +292,32 @@ /** * @brief Set the signer's uid, responcible for the signature creation. See the RFC - * 4880bis, 5.2.3.23 for details. + * 4880bis, 5.2.3.23 for details. */ void set_signer_uid(const std::string &uid); /** + * @brief Add notation. + */ + void add_notation(const std::string & name, + const std::vector &value, + bool human = true, + bool critical = false); + + /** + * @brief Add human-readable notation. + */ + void add_notation(const std::string &name, + const std::string &value, + bool critical = false); + + /** + * @brief Set the embedded signature. + * @param esig populated and calculated embedded signature. + */ + void set_embedded_sig(const pgp_signature_t &esig); + + /** * @brief Add subpacket of the specified type to v4 signature * @param type type of the subpacket * @param datalen length of the subpacket body @@ -354,6 +375,12 @@ * @param material populated signature material. */ void write_material(const pgp_signature_material_t &material); + + /** + * @brief Fill signature's hashed data. This includes all the fields from signature which + * are hashed after the previous document or key fields. + */ + void fill_hashed_data(); } pgp_signature_t; typedef std::vector pgp_signature_list_t; @@ -361,7 +388,6 @@ /* information about the validated signature */ typedef struct pgp_signature_info_t { pgp_signature_t *sig{}; /* signature, or NULL if there were parsing error */ - const pgp_key_t *signer{}; /* signer's public key if found */ bool valid{}; /* signature is cryptographically valid (but may be expired) */ bool unknown{}; /* signature is unknown - parsing error, wrong version, etc */ bool no_signer{}; /* no signer's public key available */ @@ -370,74 +396,29 @@ bool ignore_expiry{}; /* ignore signer's key expiration time */ } pgp_signature_info_t; -bool signature_set_embedded_sig(pgp_signature_t *sig, pgp_signature_t *esig); - -bool signature_add_notation_data(pgp_signature_t *sig, - bool readable, - const char * name, - const char * value); - -/** - * @brief Fill signature's hashed data. This includes all the fields from signature which are - * hashed after the previous document or key fields. - * @param sig Signature being populated - * @return true if sig->hashed_data is filled up correctly or false otherwise - */ -bool signature_fill_hashed_data(pgp_signature_t *sig); - /** * @brief Hash key packet. Used in signatures and v4 fingerprint calculation. + * Throws exception on error. * @param key key packet, must be populated - * @param hash pointer to initialized hash context - * @return true if sig->hashed_data is filled up correctly or false otherwise + * @param hash initialized hash context */ -bool signature_hash_key(const pgp_key_pkt_t *key, pgp_hash_t *hash); - -bool signature_hash_userid(const pgp_userid_pkt_t *uid, - pgp_hash_t * hash, - pgp_version_t sigver); - -bool signature_hash_signature(pgp_signature_t *sig, pgp_hash_t *hash); - -bool signature_hash_certification(const pgp_signature_t * sig, - const pgp_key_pkt_t * key, - const pgp_userid_pkt_t *userid, - pgp_hash_t * hash); - -bool signature_hash_binding(const pgp_signature_t *sig, - const pgp_key_pkt_t * key, - const pgp_key_pkt_t * subkey, - pgp_hash_t * hash); - -bool signature_hash_direct(const pgp_signature_t *sig, - const pgp_key_pkt_t * key, - pgp_hash_t * hash); - -/** - * @brief Check signature, including the expiration time, key validity and so on. - * - * @param sinfo populated signature info structure. Method will set flags valid, no_signer, - * expired. - * @param hash populated hash - * @return RNP_SUCCESS if all checks were passed, RNP_ERROR_SIGNATURE_INVALID for invalid sig, - * RNP_ERROR_SIGNATURE_EXPIRED for expired signature. Other error code means problems - * during the signature validation (out of memory, wrong parameters, etc). - */ -rnp_result_t signature_check(pgp_signature_info_t *sinfo, pgp_hash_t *hash); - -rnp_result_t signature_check_certification(pgp_signature_info_t * sinfo, - const pgp_key_pkt_t * key, - const pgp_userid_pkt_t *uid); - -rnp_result_t signature_check_binding(pgp_signature_info_t *sinfo, - const pgp_key_pkt_t * key, - const pgp_key_t * subkey); +void signature_hash_key(const pgp_key_pkt_t &key, rnp::Hash &hash); -rnp_result_t signature_check_direct(pgp_signature_info_t *sinfo, const pgp_key_pkt_t *key); +void signature_hash_userid(const pgp_userid_pkt_t &uid, rnp::Hash &hash, pgp_version_t sigver); -rnp_result_t signature_check_subkey_revocation(pgp_signature_info_t *sinfo, - const pgp_key_pkt_t * key, - const pgp_key_pkt_t * subkey); +void signature_hash_certification(const pgp_signature_t & sig, + const pgp_key_pkt_t & key, + const pgp_userid_pkt_t &userid, + rnp::Hash & hash); + +void signature_hash_binding(const pgp_signature_t &sig, + const pgp_key_pkt_t & key, + const pgp_key_pkt_t & subkey, + rnp::Hash & hash); + +void signature_hash_direct(const pgp_signature_t &sig, + const pgp_key_pkt_t & key, + rnp::Hash & hash); /** * @brief Parse stream with signatures to the signatures list. diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-write.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-write.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-write.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-write.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -48,7 +48,6 @@ #include "stream-packet.h" #include "stream-armor.h" #include "stream-sig.h" -#include "list.h" #include "pgp-key.h" #include "fingerprint.h" #include "types.h" @@ -90,7 +89,7 @@ bool has_mdc; /* encrypted with mdc, i.e. tag 18 */ bool aead; /* we use AEAD encryption */ pgp_crypt_t encrypt; /* encrypting crypto */ - pgp_hash_t mdc; /* mdc SHA1 hash */ + rnp::Hash mdc; /* mdc SHA1 hash */ pgp_aead_alg_t aalg; /* AEAD algorithm used */ uint8_t iv[PGP_AEAD_MAX_NONCE_LEN]; /* iv for AEAD mode */ uint8_t ad[PGP_AEAD_MAX_AD_LEN]; /* additional data for AEAD mode */ @@ -115,13 +114,13 @@ rnp_ctx_t * ctx; /* rnp operation context with additional parameters */ pgp_password_provider_t *password_provider; /* password provider from write handler */ std::vector siginfos; /* list of pgp_dest_signer_info_t */ - std::vector hashes; /* hashes to pass raw data through and then sign */ - bool clr_start; /* we are on the start of the line */ - uint8_t clr_buf[CT_BUF_LEN]; /* buffer to hold partial line data */ - size_t clr_buflen; /* number of bytes in buffer */ + rnp::HashList hashes; /* hashes to pass raw data through and then sign */ + bool clr_start; /* we are on the start of the line */ + uint8_t clr_buf[CT_BUF_LEN]; /* buffer to hold partial line data */ + size_t clr_buflen; /* number of bytes in buffer */ pgp_dest_signed_param_t() = default; - ~pgp_dest_signed_param_t(); + ~pgp_dest_signed_param_t() = default; } pgp_dest_signed_param_t; typedef struct pgp_dest_partial_param_t { @@ -298,7 +297,12 @@ } if (param->has_mdc) { - pgp_hash_add(¶m->mdc, buf, len); + try { + param->mdc.add(buf, len); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_BAD_STATE; + } } while (len > 0) { @@ -312,6 +316,7 @@ return RNP_SUCCESS; } +#if defined(ENABLE_AEAD) static rnp_result_t encrypted_start_aead_chunk(pgp_dest_encrypted_param_t *param, size_t idx, bool last) { @@ -383,10 +388,15 @@ return res ? RNP_SUCCESS : RNP_ERROR_BAD_PARAMETERS; } +#endif static rnp_result_t encrypted_dst_write_aead(pgp_dest_t *dst, const void *buf, size_t len) { +#if !defined(ENABLE_AEAD) + RNP_LOG("AEAD is not enabled."); + return RNP_ERROR_WRITE; +#else pgp_dest_encrypted_param_t *param = (pgp_dest_encrypted_param_t *) dst->param; size_t sz; @@ -439,33 +449,43 @@ } return RNP_SUCCESS; +#endif } static rnp_result_t encrypted_dst_finish(pgp_dest_t *dst) { - uint8_t mdcbuf[MDC_V1_SIZE]; pgp_dest_encrypted_param_t *param = (pgp_dest_encrypted_param_t *) dst->param; - rnp_result_t res; if (param->aead) { +#if !defined(ENABLE_AEAD) + RNP_LOG("AEAD is not enabled."); + rnp_result_t res = RNP_ERROR_NOT_IMPLEMENTED; +#else size_t chunks = param->chunkidx; /* if we didn't write anything in current chunk then discard it and restart */ if (param->chunkout || param->cachelen) { chunks++; } - res = encrypted_start_aead_chunk(param, chunks, true); + rnp_result_t res = encrypted_start_aead_chunk(param, chunks, true); pgp_cipher_aead_destroy(¶m->encrypt); - +#endif if (res) { + finish_streamed_packet(¶m->pkt); return res; } } else if (param->has_mdc) { + uint8_t mdcbuf[MDC_V1_SIZE]; mdcbuf[0] = MDC_PKT_TAG; mdcbuf[1] = MDC_V1_SIZE - 2; - pgp_hash_add(¶m->mdc, mdcbuf, 2); - pgp_hash_finish(¶m->mdc, &mdcbuf[2]); + try { + param->mdc.add(mdcbuf, 2); + param->mdc.finish(&mdcbuf[2]); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_BAD_STATE; + } pgp_cipher_cfb_encrypt(¶m->encrypt, mdcbuf, mdcbuf, MDC_V1_SIZE); dst_write(param->pkt.writedst, mdcbuf, MDC_V1_SIZE); } @@ -482,14 +502,15 @@ return; } - if (!param->aead) { - pgp_hash_finish(¶m->mdc, NULL); - pgp_cipher_cfb_finish(¶m->encrypt); - } else { + if (param->aead) { +#if defined(ENABLE_AEAD) pgp_cipher_aead_destroy(¶m->encrypt); +#endif + } else { + pgp_cipher_cfb_finish(¶m->encrypt); } close_streamed_packet(¶m->pkt, discard); - free(param); + delete param; dst->param = NULL; } @@ -539,7 +560,7 @@ switch (userkey->alg()) { case PGP_PKA_RSA: case PGP_PKA_RSA_ENCRYPT_ONLY: { - ret = rsa_encrypt_pkcs1(rnp_ctx_rng_handle(handler->ctx), + ret = rsa_encrypt_pkcs1(&handler->ctx->ctx->rng, &material.rsa, enckey.data(), keylen + 3, @@ -551,7 +572,8 @@ break; } case PGP_PKA_SM2: { - ret = sm2_encrypt(rnp_ctx_rng_handle(handler->ctx), +#if defined(ENABLE_SM2) + ret = sm2_encrypt(&handler->ctx->ctx->rng, &material.sm2, enckey.data(), keylen + 3, @@ -562,9 +584,18 @@ return ret; } break; +#else + RNP_LOG("sm2_encrypt is not available"); + return RNP_ERROR_NOT_IMPLEMENTED; +#endif } case PGP_PKA_ECDH: { - ret = ecdh_encrypt_pkcs5(rnp_ctx_rng_handle(handler->ctx), + if (!curve_supported(userkey->material().ec.curve)) { + RNP_LOG("ECDH encrypt: curve %d is not supported.", + (int) userkey->material().ec.curve); + return RNP_ERROR_NOT_SUPPORTED; + } + ret = ecdh_encrypt_pkcs5(&handler->ctx->ctx->rng, &material.ecdh, enckey.data(), keylen + 3, @@ -577,7 +608,7 @@ break; } case PGP_PKA_ELGAMAL: { - ret = elgamal_encrypt_pkcs1(rnp_ctx_rng_handle(handler->ctx), + ret = elgamal_encrypt_pkcs1(&handler->ctx->ctx->rng, &material.eg, enckey.data(), keylen + 3, @@ -603,6 +634,7 @@ } } +#if defined(ENABLE_AEAD) static bool encrypted_sesk_set_ad(pgp_crypt_t *crypt, pgp_sk_sesskey_t *skey) { @@ -615,6 +647,7 @@ return pgp_cipher_aead_set_ad(crypt, ad_data, 4); } +#endif static rnp_result_t encrypted_add_password(rnp_symmetric_pass_info_t * pass, @@ -626,8 +659,6 @@ pgp_sk_sesskey_t skey = {}; unsigned s2keylen; /* length of the s2k key */ pgp_crypt_t kcrypt; - uint8_t nonce[PGP_AEAD_MAX_NONCE_LEN]; - bool res; skey.alg = param->ctx->ealg; skey.s2k = pass->s2k; @@ -659,6 +690,10 @@ pgp_cipher_cfb_finish(&kcrypt); } } else { +#if !defined(ENABLE_AEAD) + RNP_LOG("AEAD support is not enabled."); + return RNP_ERROR_NOT_IMPLEMENTED; +#else /* AEAD-encrypted v5 packet */ if ((param->ctx->aalg != PGP_AEAD_EAX) && (param->ctx->aalg != PGP_AEAD_OCB)) { RNP_LOG("unsupported AEAD algorithm"); @@ -670,7 +705,9 @@ skey.ivlen = pgp_cipher_aead_nonce_len(skey.aalg); skey.enckeylen = keylen + pgp_cipher_aead_tag_len(skey.aalg); - if (!rng_get_data(rnp_ctx_rng_handle(param->ctx), skey.iv, skey.ivlen)) { + try { + param->ctx->ctx->rng.get(skey.iv, skey.ivlen); + } catch (const std::exception &e) { return RNP_ERROR_RNG; } @@ -685,17 +722,19 @@ } /* calculate nonce */ - size_t nlen = pgp_cipher_aead_nonce(skey.aalg, skey.iv, nonce, 0); + uint8_t nonce[PGP_AEAD_MAX_NONCE_LEN]; + size_t nlen = pgp_cipher_aead_nonce(skey.aalg, skey.iv, nonce, 0); /* start cipher, encrypt key and get tag */ - res = pgp_cipher_aead_start(&kcrypt, nonce, nlen) && - pgp_cipher_aead_finish(&kcrypt, skey.enckey, key, keylen); + bool res = pgp_cipher_aead_start(&kcrypt, nonce, nlen) && + pgp_cipher_aead_finish(&kcrypt, skey.enckey, key, keylen); pgp_cipher_aead_destroy(&kcrypt); if (!res) { return RNP_ERROR_BAD_STATE; } +#endif } /* Writing symmetric key encrypted session key packet */ @@ -718,8 +757,10 @@ /* initializing the mdc */ dst_write(param->pkt.writedst, &mdcver, 1); - if (!pgp_hash_create(¶m->mdc, PGP_HASH_SHA1)) { - RNP_LOG("cannot create sha1 hash"); + try { + param->mdc = rnp::Hash(PGP_HASH_SHA1); + } catch (const std::exception &e) { + RNP_LOG("cannot create sha1 hash: %s", e.what()); return RNP_ERROR_GENERIC; } } @@ -731,15 +772,17 @@ /* generating and writing iv/password check bytes */ blsize = pgp_block_size(param->ctx->ealg); - if (!rng_get_data(rnp_ctx_rng_handle(param->ctx), enchdr, blsize)) { - return RNP_ERROR_RNG; - } - - enchdr[blsize] = enchdr[blsize - 2]; - enchdr[blsize + 1] = enchdr[blsize - 1]; + try { + param->ctx->ctx->rng.get(enchdr, blsize); + enchdr[blsize] = enchdr[blsize - 2]; + enchdr[blsize + 1] = enchdr[blsize - 1]; - if (param->has_mdc) { - pgp_hash_add(¶m->mdc, enchdr, blsize + 2); + if (param->has_mdc) { + param->mdc.add(enchdr, blsize + 2); + } + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); + return RNP_ERROR_BAD_STATE; } pgp_cipher_cfb_encrypt(¶m->encrypt, enchdr, enchdr, blsize + 2); @@ -758,6 +801,10 @@ static rnp_result_t encrypted_start_aead(pgp_dest_encrypted_param_t *param, uint8_t *enckey) { +#if !defined(ENABLE_AEAD) + RNP_LOG("AEAD support is not enabled."); + return RNP_ERROR_NOT_IMPLEMENTED; +#else uint8_t hdr[4 + PGP_AEAD_MAX_NONCE_LEN]; size_t nlen; @@ -773,7 +820,9 @@ /* generate iv */ nlen = pgp_cipher_aead_nonce_len(param->ctx->aalg); - if (!rng_get_data(rnp_ctx_rng_handle(param->ctx), param->iv, nlen)) { + try { + param->ctx->ctx->rng.get(param->iv, nlen); + } catch (const std::exception &e) { return RNP_ERROR_RNG; } memcpy(hdr + 4, param->iv, nlen); @@ -798,6 +847,7 @@ } return encrypted_start_aead_chunk(param, 0, false); +#endif } static rnp_result_t @@ -833,11 +883,16 @@ } } - if (!init_dst_common(dst, sizeof(*param))) { + if (!init_dst_common(dst, 0)) { + return RNP_ERROR_OUT_OF_MEMORY; + } + try { + param = new pgp_dest_encrypted_param_t(); + dst->param = param; + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); return RNP_ERROR_OUT_OF_MEMORY; } - - param = (pgp_dest_encrypted_param_t *) dst->param; param->has_mdc = true; param->aead = handler->ctx->aalg != PGP_AEAD_NONE; param->aalg = handler->ctx->aalg; @@ -859,7 +914,9 @@ } if ((pkeycount > 0) || (skeycount > 1) || param->aead) { - if (!rng_get_data(rnp_ctx_rng_handle(handler->ctx), enckey.data(), keylen)) { + try { + handler->ctx->ctx->rng.get(enckey.data(), keylen); + } catch (const std::exception &e) { ret = RNP_ERROR_RNG; goto finish; } @@ -939,29 +996,33 @@ /* output data */ dst_write(param->writedst, buf, len); - if (eol) { - bool hashcrlf = false; - ptr = buf + len - 1; + try { + if (eol) { + bool hashcrlf = false; + ptr = buf + len - 1; + + /* skipping trailing characters - space, tab, carriage return, line feed */ + while ((ptr >= buf) && ((*ptr == CH_SPACE) || (*ptr == CH_TAB) || + (*ptr == CH_CR) || (*ptr == CH_LF))) { + if (*ptr == CH_LF) { + hashcrlf = true; + } + ptr--; + } - /* skipping trailing characters - space, tab, carriage return, line feed */ - while ((ptr >= buf) && ((*ptr == CH_SPACE) || (*ptr == CH_TAB) || (*ptr == CH_CR) || - (*ptr == CH_LF))) { - if (*ptr == CH_LF) { - hashcrlf = true; + /* hashing line body and \r\n */ + param->hashes.add(buf, ptr + 1 - buf); + if (hashcrlf) { + param->hashes.add(ST_CRLF, 2); } - ptr--; + param->clr_start = hashcrlf; + } else if (len > 0) { + /* hashing just line's data */ + param->hashes.add(buf, len); + param->clr_start = false; } - - /* hashing line body and \r\n */ - pgp_hash_list_update(param->hashes, buf, ptr + 1 - buf); - if (hashcrlf) { - pgp_hash_list_update(param->hashes, ST_CRLF, 2); - } - param->clr_start = hashcrlf; - } else if (len > 0) { - /* hashing just line's data */ - pgp_hash_list_update(param->hashes, buf, len); - param->clr_start = false; + } catch (const std::exception &e) { + RNP_LOG("failed to hash data: %s", e.what()); } } @@ -1045,56 +1106,35 @@ return RNP_SUCCESS; } -static rnp_result_t -signed_fill_signature(pgp_dest_signed_param_t *param, - pgp_signature_t * sig, - pgp_dest_signer_info_t * signer) -{ - const pgp_key_pkt_t *deckey = NULL; - pgp_hash_t hash; - pgp_password_ctx_t ctx = {.op = PGP_OP_SIGN, .key = signer->key}; - rnp_result_t ret = RNP_ERROR_GENERIC; - - /* fill signature fields */ - try { - sig->set_keyfp(signer->key->fp()); - sig->set_keyid(signer->key->keyid()); - sig->set_creation(signer->sigcreate ? signer->sigcreate : time(NULL)); - sig->set_expiration(signer->sigexpire); - } catch (const std::exception &e) { - RNP_LOG("failed to setup signature fields: %s", e.what()); - return RNP_ERROR_OUT_OF_MEMORY; - } - if (!signature_fill_hashed_data(sig)) { - RNP_LOG("failed to fill the signature data"); - return RNP_ERROR_OUT_OF_MEMORY; +static void +signed_fill_signature(pgp_dest_signed_param_t ¶m, + pgp_signature_t & sig, + pgp_dest_signer_info_t & signer) +{ + /* fill signature fields, assuming sign_init was called on it */ + if (signer.sigcreate) { + sig.set_creation(signer.sigcreate); } + sig.set_expiration(signer.sigexpire); + sig.fill_hashed_data(); - if (!pgp_hash_copy(&hash, pgp_hash_list_get(param->hashes, sig->halg))) { + const rnp::Hash *listh = param.hashes.get(sig.halg); + if (!listh) { RNP_LOG("failed to obtain hash"); - return RNP_ERROR_BAD_PARAMETERS; + throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); } + rnp::Hash hash; + listh->clone(hash); /* decrypt the secret key if needed */ - if (signer->key->encrypted()) { - deckey = pgp_decrypt_seckey(signer->key, param->password_provider, &ctx); - if (!deckey) { - RNP_LOG("wrong secret key password"); - pgp_hash_finish(&hash, NULL); - return RNP_ERROR_BAD_PASSWORD; - } - } else { - deckey = &signer->key->pkt(); + rnp::KeyLocker(*signer.key); + if (signer.key->encrypted() && + !signer.key->unlock(*param.password_provider, PGP_OP_SIGN)) { + RNP_LOG("wrong secret key password"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PASSWORD); } - /* calculate the signature */ - ret = signature_calculate(sig, &deckey->material, &hash, rnp_ctx_rng_handle(param->ctx)); - - /* destroy decrypted secret key */ - if (signer->key->encrypted()) { - delete deckey; - } - return ret; + signature_calculate(sig, signer.key->material(), hash, *param.ctx->ctx); } static rnp_result_t @@ -1102,27 +1142,24 @@ pgp_dest_signer_info_t * signer, pgp_dest_t * writedst) { - pgp_signature_t sig; - sig.version = (pgp_version_t) 4; - if (signer->onepass.version) { - sig.halg = signer->onepass.halg; - sig.palg = signer->onepass.palg; - sig.set_type(signer->onepass.type); - } else { - sig.halg = pgp_hash_adjust_alg_to_key(signer->halg, &signer->key->pkt()); - sig.palg = signer->key->alg(); - sig.set_type(param->ctx->detached ? PGP_SIG_BINARY : PGP_SIG_TEXT); - } - - rnp_result_t ret = signed_fill_signature(param, &sig, signer); - if (ret) { - return ret; - } try { + pgp_signature_t sig; + if (signer->onepass.version) { + signer->key->sign_init(sig, signer->onepass.halg); + sig.palg = signer->onepass.palg; + sig.set_type(signer->onepass.type); + } else { + signer->key->sign_init(sig, signer->halg); + /* line below should be checked */ + sig.set_type(param->ctx->detached ? PGP_SIG_BINARY : PGP_SIG_TEXT); + } + signed_fill_signature(*param, sig, *signer); sig.write(*writedst); return writedst->werr; + } catch (const rnp::rnp_exception &e) { + return e.code(); } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); + RNP_LOG("Failed to write signature: %s", e.what()); return RNP_ERROR_WRITE; } } @@ -1209,7 +1246,7 @@ signed_dst_update(pgp_dest_t *dst, const void *buf, size_t len) { pgp_dest_signed_param_t *param = (pgp_dest_signed_param_t *) dst->param; - pgp_hash_list_update(param->hashes, buf, len); + param->hashes.add(buf, len); } static rnp_result_t @@ -1221,6 +1258,12 @@ RNP_LOG("secret key required for signing"); return RNP_ERROR_BAD_PARAMETERS; } + /* validate signing key material if didn't before */ + signer->key->pkt().material.validate(*param->ctx->ctx, false); + if (!signer->key->pkt().material.valid()) { + RNP_LOG("attempt to sign to the key with invalid material"); + return RNP_ERROR_NO_SUITABLE_KEY; + } /* copy fields */ sinfo.key = signer->key; @@ -1229,7 +1272,10 @@ /* Add hash to the list */ sinfo.halg = pgp_hash_adjust_alg_to_key(signer->halg, &signer->key->pkt()); - if (!pgp_hash_list_add(param->hashes, sinfo.halg)) { + try { + param->hashes.add_alg(sinfo.halg); + } catch (const std::exception &e) { + RNP_LOG("%s", e.what()); return RNP_ERROR_BAD_PARAMETERS; } @@ -1275,19 +1321,11 @@ } } -pgp_dest_signed_param_t::~pgp_dest_signed_param_t() -{ - for (auto &hash : hashes) { - pgp_hash_finish(&hash, NULL); - } -} - static rnp_result_t init_signed_dst(pgp_write_handler_t *handler, pgp_dest_t *dst, pgp_dest_t *writedst) { pgp_dest_signed_param_t *param; rnp_result_t ret = RNP_ERROR_GENERIC; - const char * hname; if (!handler->key_provider) { RNP_LOG("no key provider"); @@ -1341,10 +1379,10 @@ dst_write(param->writedst, ST_CRLF, strlen(ST_CRLF)); dst_write(param->writedst, ST_HEADER_HASH, strlen(ST_HEADER_HASH)); - for (const auto &hash : param->hashes) { - hname = pgp_hash_name(&hash); + for (const auto &hash : param->hashes.hashes()) { + auto hname = rnp::Hash::name(hash.alg()); dst_write(param->writedst, hname, strlen(hname)); - if (&hash != ¶m->hashes.back()) { + if (&hash != ¶m->hashes.hashes().back()) { dst_write(param->writedst, ST_COMMA, 1); } } @@ -1965,16 +2003,15 @@ } rnp_result_t -rnp_raw_encrypt_src(pgp_source_t &src, pgp_dest_t &dst, const std::string &password) +rnp_raw_encrypt_src(pgp_source_t & src, + pgp_dest_t & dst, + const std::string & password, + rnp::SecurityContext &secctx) { pgp_write_handler_t handler = {}; rnp_ctx_t ctx; - rng_t rng = {}; - if (!rng_init(&rng, RNG_SYSTEM)) { - return RNP_ERROR_BAD_STATE; - } - ctx.rng = &rng; + ctx.ctx = &secctx; ctx.ealg = DEFAULT_PGP_SYMM_ALG; handler.ctx = &ctx; pgp_dest_t encrypted = {}; @@ -1993,6 +2030,5 @@ ret = dst_write_src(&src, &encrypted); done: dst_close(&encrypted, ret); - rng_destroy(&rng); return ret; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-write.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-write.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/librepgp/stream-write.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/librepgp/stream-write.h 2022-04-15 07:49:22.000000000 +0000 @@ -82,8 +82,9 @@ const std::string &filename, uint32_t modtime); -rnp_result_t rnp_raw_encrypt_src(pgp_source_t & src, - pgp_dest_t & dst, - const std::string &password); +rnp_result_t rnp_raw_encrypt_src(pgp_source_t & src, + pgp_dest_t & dst, + const std::string & password, + rnp::SecurityContext &secctx); #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/CMakeLists.txt thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/CMakeLists.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/CMakeLists.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/CMakeLists.txt 2022-04-15 07:49:22.000000000 +0000 @@ -85,7 +85,7 @@ ) endif() -if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +if(WIN32 AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) target_link_libraries(rnp PRIVATE regex) elseif(MSVC) add_compile_definitions(RNP_USE_STD_REGEX) diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/fficli.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/fficli.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/fficli.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/fficli.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "config.h" #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #ifdef _MSC_VER #include "uniwin.h" @@ -45,8 +47,10 @@ #ifndef _WIN32 #include +#ifdef HAVE_SYS_RESOURCE_H #include #endif +#endif #include "config.h" #include "fficli.h" @@ -217,7 +221,7 @@ return false; } - rnp_strip_eol(reply); + rnp::strip_eol(reply); if (strlen(reply) > 0) { if (toupper(reply[0]) == 'Y') { @@ -235,57 +239,67 @@ return false; } +static bool +rnp_ask_filename(const std::string &msg, std::string &res, cli_rnp_t &rnp) +{ + fprintf(rnp.userio_out, "%s", msg.c_str()); + fflush(rnp.userio_out); + char fname[128] = {0}; + std::string path; + do { + if (!fgets(fname, sizeof(fname), rnp.userio_in)) { + return false; + } + path = path + std::string(fname); + if (rnp::strip_eol(path)) { + res = path; + return true; + } + if (path.size() >= 2048) { + fprintf(rnp.userio_out, "%s", "Too long filename, aborting."); + fflush(rnp.userio_out); + return false; + } + } while (1); +} + /** @brief checks whether file exists already and asks user for the new filename - * @param path output file name with path. May be NULL, then user is asked for it. - * @param newpath preallocated pointer which will store the result on success - * @param maxlen maximum number of chars in newfile, including the trailing \0 - * @param overwrite whether it is allowed to overwrite output file by default + * @param path output file name with path. May be an empty string, then user is asked for it. + * @param res resulting output path will be stored here. + * @param rnp initialized cli_rnp_t structure with additional data * @return true on success, or false otherwise (user cancels the operation) **/ static bool -rnp_get_output_filename( - const char *path, char *newpath, size_t maxlen, bool overwrite, cli_rnp_t *rnp) +rnp_get_output_filename(const std::string &path, std::string &res, cli_rnp_t &rnp) { - if (!path || !path[0]) { - fprintf(rnp->userio_out, "Please enter the output filename: "); - fflush(rnp->userio_out); - if (fgets(newpath, maxlen, rnp->userio_in) == NULL) { - return false; - } - rnp_strip_eol(newpath); - } else { - strncpy(newpath, path, maxlen - 1); - newpath[maxlen - 1] = '\0'; + std::string newpath = path; + if (newpath.empty() && + !rnp_ask_filename("Please enter the output filename: ", newpath, rnp)) { + return false; } while (true) { - if (rnp_file_exists(newpath)) { - if (overwrite) { - rnp_unlink(newpath); - return true; - } - - if (cli_rnp_get_confirmation( - rnp, "File '%s' already exists. Would you like to overwrite it?", newpath)) { - rnp_unlink(newpath); - return true; - } - - fprintf(rnp->userio_out, "Please enter the new filename: "); - fflush(rnp->userio_out); - if (fgets(newpath, maxlen, rnp->userio_in) == NULL) { - return false; - } - - rnp_strip_eol(newpath); - - if (strlen(newpath) == 0) { - return false; - } - } else { + if (!rnp_file_exists(newpath.c_str())) { + res = newpath; return true; } + if (rnp.cfg().get_bool(CFG_OVERWRITE) || + cli_rnp_get_confirmation( + &rnp, + "File '%s' already exists. Would you like to overwrite it?", + newpath.c_str())) { + rnp_unlink(newpath.c_str()); + res = newpath; + return true; + } + + if (!rnp_ask_filename("Please enter the new filename: ", newpath, rnp)) { + return false; + } + if (newpath.empty()) { + return false; + } } } @@ -336,7 +350,7 @@ goto end; } - rnp_strip_eol(buffer); + rnp::strip_eol(buffer); ok = true; end: #ifndef _WIN32 @@ -344,7 +358,7 @@ tcsetattr(fileno(in), TCSAFLUSH, &saved_flags); } #endif - if (in != userio_in) { + if (in && (in != userio_in)) { fclose(in); } return ok; @@ -431,7 +445,7 @@ if (!fgets(buf, buf_len, fp)) { return false; } - rnp_strip_eol(buf); + rnp::strip_eol(buf); return true; } @@ -456,231 +470,193 @@ return true; } -rnp_cfg & -cli_rnp_cfg(cli_rnp_t &rnp) -{ - return rnp.cfg; -} - -const std::string -cli_rnp_defkey(cli_rnp_t *rnp) -{ - return rnp->cfg.get_str(CFG_KR_DEF_KEY); -} - -const std::string -cli_rnp_pubpath(cli_rnp_t *rnp) -{ - return rnp->cfg.get_str(CFG_KR_PUB_PATH); -} -const std::string -cli_rnp_secpath(cli_rnp_t *rnp) -{ - return rnp->cfg.get_str(CFG_KR_SEC_PATH); -} - -const std::string -cli_rnp_pubformat(cli_rnp_t *rnp) -{ - return rnp->cfg.get_str(CFG_KR_PUB_FORMAT); -} - -const std::string -cli_rnp_secformat(cli_rnp_t *rnp) -{ - return rnp->cfg.get_str(CFG_KR_SEC_FORMAT); -} - bool -cli_rnp_init(cli_rnp_t *rnp, const rnp_cfg &cfg) +cli_rnp_t::init(const rnp_cfg &cfg) { - bool coredumps = true; + cfg_.copy(cfg); - if (!cli_rnp_baseinit(rnp)) { - return false; + /* Configure user's io streams. */ + if (!cfg_.get_bool(CFG_NOTTY)) { + userio_in = (isatty(fileno(stdin)) ? stdin : fopen("/dev/tty", "r")); + userio_in = (userio_in ? userio_in : stdin); + userio_out = (isatty(fileno(stdout)) ? stdout : fopen("/dev/tty", "a+")); + userio_out = (userio_out ? userio_out : stdout); + } else { + userio_in = stdin; + userio_out = stdout; } - rnp->cfg.copy(cfg); +#ifndef _WIN32 /* If system resource constraints are in effect then attempt to * disable core dumps. */ - if (!rnp->cfg.get_bool(CFG_COREDUMPS)) { + bool coredumps = true; + if (!cfg_.get_bool(CFG_COREDUMPS)) { #ifdef HAVE_SYS_RESOURCE_H coredumps = !disable_core_dumps(); #endif } if (coredumps) { - ERR_MSG( - "rnp: warning: core dumps may be enabled, sensitive data may be leaked to disk"); + ERR_MSG("warning: core dumps may be enabled, sensitive data may be leaked to disk"); } +#endif /* Configure the results stream. */ // TODO: UTF8? - const std::string &ress = rnp->cfg.get_str(CFG_IO_RESS); + const std::string &ress = cfg_.get_str(CFG_IO_RESS); if (ress.empty() || (ress == "")) { - rnp->resfp = stderr; + resfp = stderr; } else if (ress == "") { - rnp->resfp = stdout; - } else if (!(rnp->resfp = rnp_fopen(ress.c_str(), "w"))) { + resfp = stdout; + } else if (!(resfp = rnp_fopen(ress.c_str(), "w"))) { ERR_MSG("cannot open results %s for writing", ress.c_str()); return false; } bool res = false; - const std::string pformat = cli_rnp_pubformat(rnp); - const std::string sformat = cli_rnp_secformat(rnp); + const std::string pformat = pubformat(); + const std::string sformat = secformat(); if (pformat.empty() || sformat.empty()) { ERR_MSG("Unknown public or secret keyring format"); return false; } - if (rnp_ffi_create(&rnp->ffi, pformat.c_str(), sformat.c_str())) { + if (rnp_ffi_create(&ffi, pformat.c_str(), sformat.c_str())) { ERR_MSG("failed to initialize FFI"); return false; } // by default use stdin password provider - if (rnp_ffi_set_pass_provider(rnp->ffi, ffi_pass_callback_stdin, rnp)) { + if (rnp_ffi_set_pass_provider(ffi, ffi_pass_callback_stdin, this)) { goto done; } // setup file/pipe password input if requested - if (rnp->cfg.get_int(CFG_PASSFD, -1) >= 0) { - if (!set_pass_fd(&rnp->passfp, rnp->cfg.get_int(CFG_PASSFD))) { + if (cfg_.get_int(CFG_PASSFD, -1) >= 0) { + if (!set_pass_fd(&passfp, cfg_.get_int(CFG_PASSFD))) { goto done; } - if (rnp_ffi_set_pass_provider(rnp->ffi, ffi_pass_callback_file, rnp->passfp)) { + if (rnp_ffi_set_pass_provider(ffi, ffi_pass_callback_file, passfp)) { goto done; } } - rnp->pswdtries = MAX_PASSWORD_ATTEMPTS; + pswdtries = MAX_PASSWORD_ATTEMPTS; res = true; done: if (!res) { - rnp_ffi_destroy(rnp->ffi); - rnp->ffi = NULL; + rnp_ffi_destroy(ffi); + ffi = NULL; } return res; } -bool -cli_rnp_baseinit(cli_rnp_t *rnp) -{ - /* Configure user's io streams. */ - rnp->userio_in = (isatty(fileno(stdin)) ? stdin : fopen("/dev/tty", "r")); - rnp->userio_in = (rnp->userio_in ? rnp->userio_in : stdin); - rnp->userio_out = (isatty(fileno(stdout)) ? stdout : fopen("/dev/tty", "a+")); - rnp->userio_out = (rnp->userio_out ? rnp->userio_out : stdout); - return true; -} - void -cli_rnp_end(cli_rnp_t *rnp) +cli_rnp_t::end() { - if (rnp->passfp) { - fclose(rnp->passfp); - rnp->passfp = NULL; + if (passfp) { + fclose(passfp); + passfp = NULL; } - if (rnp->resfp && (rnp->resfp != stderr) && (rnp->resfp != stdout)) { - fclose(rnp->resfp); - rnp->resfp = NULL; + if (resfp && (resfp != stderr) && (resfp != stdout)) { + fclose(resfp); + resfp = NULL; } - if (rnp->userio_in && rnp->userio_in != stdin) { - fclose(rnp->userio_in); + if (userio_in && userio_in != stdin) { + fclose(userio_in); } - rnp->userio_in = NULL; - if (rnp->userio_out && rnp->userio_out != stdout) { - fclose(rnp->userio_out); + userio_in = NULL; + if (userio_out && userio_out != stdout) { + fclose(userio_out); } - rnp->userio_out = NULL; - rnp_ffi_destroy(rnp->ffi); - rnp->ffi = NULL; - rnp->cfg.clear(); + userio_out = NULL; + rnp_ffi_destroy(ffi); + ffi = NULL; + cfg_.clear(); } bool -cli_rnp_load_keyrings(cli_rnp_t *rnp, bool loadsecret) +cli_rnp_t::load_keyring(bool secret) { - rnp_input_t keyin = NULL; - size_t keycount = 0; - bool res = false; + const char *path = secret ? secpath().c_str() : pubpath().c_str(); + bool dir = secret && (secformat() == RNP_KEYSTORE_G10); + if (dir && !rnp_dir_exists(path)) { + ERR_MSG("warning: keyring directory at '%s' doesn't exist.", path); + return true; + } + if (!dir && !rnp_file_exists(path)) { + ERR_MSG("warning: keyring at path '%s' doesn't exist.", path); + return true; + } - if (rnp_unload_keys(rnp->ffi, RNP_KEY_UNLOAD_PUBLIC)) { - ERR_MSG("failed to clear public keyring"); - goto done; + rnp_input_t keyin = NULL; + if (rnp_input_from_path(&keyin, path)) { + ERR_MSG("warning: failed to open keyring at path '%s' for reading.", path); + return true; } - if (rnp_input_from_path(&keyin, cli_rnp_pubpath(rnp).c_str())) { - ERR_MSG("wrong pubring path"); - goto done; + const char * format = secret ? secformat().c_str() : pubformat().c_str(); + uint32_t flags = secret ? RNP_LOAD_SAVE_SECRET_KEYS : RNP_LOAD_SAVE_PUBLIC_KEYS; + rnp_result_t ret = rnp_load_keys(ffi, format, keyin, flags); + if (ret) { + ERR_MSG("error: failed to load keyring from '%s'", path); } + rnp_input_destroy(keyin); - if (rnp_load_keys( - rnp->ffi, cli_rnp_pubformat(rnp).c_str(), keyin, RNP_LOAD_SAVE_PUBLIC_KEYS)) { - ERR_MSG("cannot read pub keyring"); - goto done; + if (ret) { + return false; } - rnp_input_destroy(keyin); - keyin = NULL; + size_t keycount = 0; + if (secret) { + (void) rnp_get_secret_key_count(ffi, &keycount); + } else { + (void) rnp_get_public_key_count(ffi, &keycount); + } + if (!keycount) { + ERR_MSG("warning: no keys were loaded from the keyring '%s'.", path); + } + return true; +} - if (rnp_get_public_key_count(rnp->ffi, &keycount)) { - goto done; +bool +cli_rnp_t::load_keyrings(bool loadsecret) +{ + /* Read public keys */ + if (rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC)) { + ERR_MSG("failed to clear public keyring"); + return false; } - if (keycount < 1) { - ERR_MSG("pub keyring '%s' is empty", cli_rnp_pubpath(rnp).c_str()); - goto done; + if (!load_keyring(false)) { + return false; } /* Only read secret keys if we need to */ if (loadsecret) { - if (rnp_unload_keys(rnp->ffi, RNP_KEY_UNLOAD_SECRET)) { + if (rnp_unload_keys(ffi, RNP_KEY_UNLOAD_SECRET)) { ERR_MSG("failed to clear secret keyring"); - goto done; - } - - if (rnp_input_from_path(&keyin, cli_rnp_secpath(rnp).c_str())) { - ERR_MSG("wrong secring path"); - goto done; - } - - if (rnp_load_keys( - rnp->ffi, cli_rnp_secformat(rnp).c_str(), keyin, RNP_LOAD_SAVE_SECRET_KEYS)) { - ERR_MSG("cannot read sec keyring"); - goto done; - } - - rnp_input_destroy(keyin); - keyin = NULL; - - if (rnp_get_secret_key_count(rnp->ffi, &keycount)) { - goto done; + return false; } - if (keycount < 1) { - ERR_MSG("sec keyring '%s' is empty", cli_rnp_secpath(rnp).c_str()); - goto done; + if (!load_keyring(true)) { + return false; } } - if (cli_rnp_defkey(rnp).empty()) { - cli_rnp_set_default_key(rnp); + if (defkey().empty()) { + set_defkey(); } - res = true; -done: - rnp_input_destroy(keyin); - return res; + return true; } void -cli_rnp_set_default_key(cli_rnp_t *rnp) +cli_rnp_t::set_defkey() { rnp_identifier_iterator_t it = NULL; rnp_key_handle_t handle = NULL; const char * grip = NULL; - cli_rnp_cfg(*rnp).unset(CFG_KR_DEF_KEY); - if (rnp_identifier_iterator_create(rnp->ffi, &it, "grip")) { + cfg_.unset(CFG_KR_DEF_KEY); + if (rnp_identifier_iterator_create(ffi, &it, "grip")) { ERR_MSG("failed to create key iterator"); return; } @@ -692,7 +668,7 @@ if (!grip) { break; } - if (rnp_locate_key(rnp->ffi, "grip", grip, &handle)) { + if (rnp_locate_key(ffi, "grip", grip, &handle)) { ERR_MSG("failed to locate key"); continue; } @@ -702,8 +678,8 @@ if (rnp_key_have_secret(handle, &is_secret)) { goto next; } - if (!cli_rnp_cfg(*rnp).has(CFG_KR_DEF_KEY) || is_secret) { - cli_rnp_cfg(*rnp).set_str(CFG_KR_DEF_KEY, grip); + if (!cfg_.has(CFG_KR_DEF_KEY) || is_secret) { + cfg_.set_str(CFG_KR_DEF_KEY, grip); /* if we have secret primary key then use it as default */ if (is_secret) { break; @@ -717,6 +693,208 @@ rnp_identifier_iterator_destroy(it); } +bool +cli_rnp_t::is_cv25519_subkey(rnp_key_handle_t handle) +{ + bool primary = false; + if (rnp_key_is_primary(handle, &primary)) { + ERR_MSG("Error: failed to check for subkey."); + return false; + } + if (primary) { + return false; + } + char *alg = NULL; + if (rnp_key_get_alg(handle, &alg)) { + ERR_MSG("Error: failed to check key's alg."); + return false; + } + bool ecdh = !strcmp(alg, RNP_ALGNAME_ECDH); + rnp_buffer_destroy(alg); + if (!ecdh) { + return false; + } + char *curve = NULL; + if (rnp_key_get_curve(handle, &curve)) { + ERR_MSG("Error: failed to check key's curve."); + return false; + } + bool cv25519 = !strcmp(curve, "Curve25519"); + rnp_buffer_destroy(curve); + return cv25519; +} + +bool +cli_rnp_t::get_protection(rnp_key_handle_t handle, + std::string & hash, + std::string & cipher, + size_t & iterations) +{ + bool prot = false; + if (rnp_key_is_protected(handle, &prot)) { + ERR_MSG("Error: failed to check key's protection."); + return false; + } + if (!prot) { + hash = ""; + cipher = ""; + iterations = 0; + return true; + } + + char *val = NULL; + try { + if (rnp_key_get_protection_hash(handle, &val)) { + ERR_MSG("Error: failed to retrieve key's protection hash."); + return false; + } + hash = val; + rnp_buffer_destroy(val); + if (rnp_key_get_protection_cipher(handle, &val)) { + ERR_MSG("Error: failed to retrieve key's protection cipher."); + return false; + } + cipher = val; + rnp_buffer_destroy(val); + if (rnp_key_get_protection_iterations(handle, &iterations)) { + ERR_MSG("Error: failed to retrieve key's protection iterations."); + return false; + } + return true; + } catch (const std::exception &e) { + ERR_MSG("Error: failed to retrieve key's properties: %s", e.what()); + rnp_buffer_destroy(val); + return false; + } +} + +bool +cli_rnp_t::check_cv25519_bits(rnp_key_handle_t key, char *prot_password, bool &tweaked) +{ + /* unlock key first to check whether bits are tweaked */ + if (prot_password && rnp_key_unlock(key, prot_password)) { + ERR_MSG("Error: failed to unlock key. Did you specify valid password?"); + return false; + } + rnp_result_t ret = rnp_key_25519_bits_tweaked(key, &tweaked); + if (ret) { + ERR_MSG("Error: failed to check whether key's bits are tweaked."); + } + if (prot_password) { + rnp_key_lock(key); + } + return !ret; +} + +bool +cli_rnp_t::fix_cv25519_subkey(const std::string &key, bool checkonly) +{ + std::vector keys; + if (!cli_rnp_keys_matching_string( + this, keys, key, CLI_SEARCH_SECRET | CLI_SEARCH_SUBKEYS)) { + ERR_MSG("Secret keys matching '%s' not found.", key.c_str()); + return false; + } + bool res = false; + std::string prot_hash; + std::string prot_cipher; + size_t prot_iterations; + char * prot_password = NULL; + bool tweaked = false; + + if (keys.size() > 1) { + ERR_MSG( + "Ambiguous input: too many keys found for '%s'. Did you use keyid or fingerprint?", + key.c_str()); + goto done; + } + cli_rnp_print_key_info(userio_out, ffi, keys[0], true, false); + if (!is_cv25519_subkey(keys[0])) { + ERR_MSG("Error: specified key is not Curve25519 ECDH subkey."); + goto done; + } + + if (!get_protection(keys[0], prot_hash, prot_cipher, prot_iterations)) { + goto done; + } + + if (!prot_hash.empty() && + (rnp_request_password(ffi, keys[0], "unprotect", &prot_password) || !prot_password)) { + ERR_MSG("Error: failed to obtain protection password."); + goto done; + } + + if (!check_cv25519_bits(keys[0], prot_password, tweaked)) { + goto done; + } + + if (checkonly) { + fprintf(userio_out, + tweaked ? "Cv25519 key bits are set correctly and do not require fixing.\n" : + "Warning: Cv25519 key bits need fixing.\n"); + res = tweaked; + goto done; + } + + if (tweaked) { + ERR_MSG("Warning: key's bits are fixed already, no action is required."); + res = true; + goto done; + } + + /* now unprotect so we can tweak bits */ + if (!prot_hash.empty()) { + if (rnp_key_unprotect(keys[0], prot_password)) { + ERR_MSG("Error: failed to unprotect key. Did you specify valid password?"); + goto done; + } + if (rnp_key_unlock(keys[0], NULL)) { + ERR_MSG("Error: failed to unlock key."); + goto done; + } + } + + /* tweak key bits and protect back */ + if (rnp_key_25519_bits_tweak(keys[0])) { + ERR_MSG("Error: failed to tweak key's bits."); + goto done; + } + + if (!prot_hash.empty() && rnp_key_protect(keys[0], + prot_password, + prot_cipher.c_str(), + NULL, + prot_hash.c_str(), + prot_iterations)) { + ERR_MSG("Error: failed to protect key back."); + goto done; + } + + res = cli_rnp_save_keyrings(this); +done: + clear_key_handles(keys); + if (prot_password) { + rnp_buffer_clear(prot_password, strlen(prot_password) + 1); + rnp_buffer_destroy(prot_password); + } + return res; +} + +bool +cli_rnp_t::edit_key(const std::string &key) +{ + if (cfg().get_bool(CFG_CHK_25519_BITS)) { + return fix_cv25519_subkey(key, true); + } + if (cfg().get_bool(CFG_FIX_25519_BITS)) { + return fix_cv25519_subkey(key, false); + } + + /* more options, like --passwd, --unprotect, --expiration are to come */ + ERR_MSG("You should specify at least one editing option for --edit-key."); + return false; +} + const char * json_obj_get_str(json_object *obj, const char *key) { @@ -810,6 +988,27 @@ return result; } +static const std::string alg_aliases[] = { + "3DES", "TRIPLEDES", "3-DES", "TRIPLEDES", "CAST-5", "CAST5", + "AES", "AES128", "AES-128", "AES128", "AES-192", "AES192", + "AES-256", "AES256", "CAMELLIA-128", "CAMELLIA128", "CAMELLIA-192", "CAMELLIA192", + "CAMELLIA-256", "CAMELLIA256", "SHA", "SHA1", "SHA-1", "SHA1", + "SHA-224", "SHA224", "SHA-256", "SHA256", "SHA-384", "SHA384", + "SHA-512", "SHA512", "RIPEMD-160", "RIPEMD160"}; + +const std::string +cli_rnp_alg_to_ffi(const std::string alg) +{ + size_t count = sizeof(alg_aliases) / sizeof(alg_aliases[0]); + assert((count % 2) == 0); + for (size_t idx = 0; idx < count; idx += 2) { + if (rnp_casecmp(alg, alg_aliases[idx])) { + return alg_aliases[idx + 1]; + } + } + return alg; +} + #ifndef RNP_USE_STD_REGEX static std::string cli_rnp_unescape_for_regcomp(const std::string &src) @@ -999,14 +1198,14 @@ bool cli_rnp_save_keyrings(cli_rnp_t *rnp) { - rnp_output_t output = NULL; - rnp_result_t pub_ret = 0; - rnp_result_t sec_ret = 0; - const std::string ppath = cli_rnp_pubpath(rnp); - const std::string spath = cli_rnp_secpath(rnp); + rnp_output_t output = NULL; + rnp_result_t pub_ret = 0; + rnp_result_t sec_ret = 0; + const std::string &ppath = rnp->pubpath(); + const std::string &spath = rnp->secpath(); // check whether we have G10 secret keyring - then need to create directory - if (cli_rnp_secformat(rnp) == "G10") { + if (rnp->secformat() == "G10") { struct stat path_stat; if (rnp_stat(spath.c_str(), &path_stat) != -1) { if (!S_ISDIR(path_stat.st_mode)) { @@ -1027,8 +1226,8 @@ // public keyring if (!(pub_ret = rnp_output_to_path(&output, ppath.c_str()))) { - pub_ret = rnp_save_keys( - rnp->ffi, cli_rnp_pubformat(rnp).c_str(), output, RNP_LOAD_SAVE_PUBLIC_KEYS); + pub_ret = + rnp_save_keys(rnp->ffi, rnp->pubformat().c_str(), output, RNP_LOAD_SAVE_PUBLIC_KEYS); rnp_output_destroy(output); } if (pub_ret) { @@ -1037,8 +1236,8 @@ // secret keyring if (!(sec_ret = rnp_output_to_path(&output, spath.c_str()))) { - sec_ret = rnp_save_keys( - rnp->ffi, cli_rnp_secformat(rnp).c_str(), output, RNP_LOAD_SAVE_SECRET_KEYS); + sec_ret = + rnp_save_keys(rnp->ffi, rnp->secformat().c_str(), output, RNP_LOAD_SAVE_SECRET_KEYS); rnp_output_destroy(output); } if (sec_ret) { @@ -1052,7 +1251,7 @@ cli_rnp_generate_key(cli_rnp_t *rnp, const char *username) { /* set key generation parameters to rnp_cfg_t */ - rnp_cfg &cfg = cli_rnp_cfg(*rnp); + rnp_cfg &cfg = rnp->cfg(); if (!cli_rnp_set_generate_params(cfg)) { ERR_MSG("Key generation setup failed."); return false; @@ -1083,7 +1282,7 @@ } if (cfg.has(CFG_KG_PRIMARY_EXPIRATION)) { uint32_t expiration = 0; - if (get_expiration(cfg.get_cstr(CFG_KG_PRIMARY_EXPIRATION), &expiration) || + if (!cfg.get_expiration(CFG_KG_PRIMARY_EXPIRATION, expiration) || rnp_op_generate_set_expiration(genkey, expiration)) { ERR_MSG("Failed to set primary key expiration."); goto done; @@ -1125,7 +1324,7 @@ } if (cfg.has(CFG_KG_SUBKEY_EXPIRATION)) { uint32_t expiration = 0; - if (get_expiration(cfg.get_cstr(CFG_KG_SUBKEY_EXPIRATION), &expiration) || + if (!cfg.get_expiration(CFG_KG_SUBKEY_EXPIRATION, expiration) || rnp_op_generate_set_expiration(genkey, expiration)) { ERR_MSG("Failed to set subkey expiration."); goto done; @@ -1501,12 +1700,11 @@ /* search for default key */ if (keys.empty() && (flags & CLI_SEARCH_DEFAULT)) { - if (cli_rnp_defkey(rnp).empty()) { + if (rnp->defkey().empty()) { ERR_MSG("No userid or default key for operation"); goto done; } - cli_rnp_keys_matching_string( - rnp, keys, cli_rnp_defkey(rnp), flags & ~CLI_SEARCH_DEFAULT); + cli_rnp_keys_matching_string(rnp, keys, rnp->defkey(), flags & ~CLI_SEARCH_DEFAULT); if (keys.empty()) { ERR_MSG("Default key not found"); } @@ -1745,6 +1943,12 @@ return true; } +/* This produces + runtime error: call to function stdout_writer(void*, void const*, unsigned long) through + pointer to incorrect function type 'bool (*)(void *, const void *, unsigned long)' */ +#if defined(__clang__) +__attribute__((no_sanitize("undefined"))) +#endif static bool stdout_writer(void *app_ctx, const void *buf, size_t len) { @@ -1752,35 +1956,80 @@ return (wlen >= 0) && (size_t) wlen == len; } +rnp_input_t +cli_rnp_input_from_specifier(cli_rnp_t &rnp, const std::string &spec, bool *is_path) +{ + rnp_input_t input = NULL; + rnp_result_t res = RNP_ERROR_GENERIC; + bool path = false; + if (spec.empty() || (spec == "-")) { + /* input from stdin */ + res = rnp_input_from_callback(&input, stdin_reader, NULL, NULL); + } else if ((spec.size() > 4) && (spec.compare(0, 4, "env:") == 0)) { + /* input from an environment variable */ + const char *envval = getenv(spec.c_str() + 4); + if (!envval) { + ERR_MSG("Failed to get value of the environment variable '%s'.", spec.c_str() + 4); + return NULL; + } + res = rnp_input_from_memory(&input, (const uint8_t *) envval, strlen(envval), true); + } else { + /* input from path */ + res = rnp_input_from_path(&input, spec.c_str()); + path = true; + } + + if (res) { + return NULL; + } + if (is_path) { + *is_path = path; + } + return input; +} + +rnp_output_t +cli_rnp_output_to_specifier(cli_rnp_t &rnp, const std::string &spec, bool discard) +{ + rnp_output_t output = NULL; + rnp_result_t res = RNP_ERROR_GENERIC; + std::string path = spec; + if (discard) { + res = rnp_output_to_null(&output); + } else if (spec.empty() || (spec == "-")) { + res = rnp_output_to_callback(&output, stdout_writer, NULL, NULL); + } else if (!rnp_get_output_filename(spec, path, rnp)) { + ERR_MSG("Operation failed: file '%s' already exists.", spec.c_str()); + res = RNP_ERROR_BAD_PARAMETERS; + } else { + res = rnp_output_to_file(&output, path.c_str(), RNP_OUTPUT_FILE_OVERWRITE); + } + return res ? NULL : output; +} + bool cli_rnp_export_keys(cli_rnp_t *rnp, const char *filter) { - bool secret = cli_rnp_cfg(*rnp).get_bool(CFG_SECRET); + bool secret = rnp->cfg().get_bool(CFG_SECRET); int flags = secret ? CLI_SEARCH_SECRET : 0; std::vector keys; if (!cli_rnp_keys_matching_string(rnp, keys, filter, flags)) { - fprintf(rnp->userio_out, "Key(s) matching '%s' not found.\n", filter); + ERR_MSG("Key(s) matching '%s' not found.", filter); return false; } - rnp_output_t output = NULL; - rnp_output_t armor = NULL; - const std::string &file = cli_rnp_cfg(*rnp).get_str(CFG_OUTFILE); - rnp_result_t ret; - uint32_t base_flags = secret ? RNP_KEY_EXPORT_SECRET : RNP_KEY_EXPORT_PUBLIC; - bool result = false; - - if (!file.empty()) { - uint32_t flags = cli_rnp_cfg(*rnp).get_bool(CFG_FORCE) ? RNP_OUTPUT_FILE_OVERWRITE : 0; - ret = rnp_output_to_file(&output, file.c_str(), flags); - } else { - ret = rnp_output_to_callback(&output, stdout_writer, NULL, NULL); - } - if (ret) { + rnp_output_t output = NULL; + rnp_output_t armor = NULL; + uint32_t base_flags = secret ? RNP_KEY_EXPORT_SECRET : RNP_KEY_EXPORT_PUBLIC; + bool result = false; + + output = cli_rnp_output_to_specifier(*rnp, rnp->cfg().get_str(CFG_OUTFILE)); + if (!output) { goto done; } + /* We need single armored stream for all of the keys */ if (rnp_output_to_armor(output, &armor, secret ? "secret key" : "public key")) { goto done; } @@ -1821,20 +2070,12 @@ clear_key_handles(keys); return false; } - rnp_cfg & cfg = cli_rnp_cfg(*rnp); - const std::string &file = cfg.get_str(CFG_OUTFILE); - rnp_result_t ret = RNP_ERROR_GENERIC; - rnp_output_t output = NULL; - rnp_output_t armored = NULL; - bool result = false; + rnp_output_t output = NULL; + rnp_output_t armored = NULL; + bool result = false; - if (!file.empty()) { - uint32_t flags = cfg.get_bool(CFG_FORCE) ? RNP_OUTPUT_FILE_OVERWRITE : 0; - ret = rnp_output_to_file(&output, file.c_str(), flags); - } else { - ret = rnp_output_to_callback(&output, stdout_writer, NULL, NULL); - } - if (ret) { + output = cli_rnp_output_to_specifier(*rnp, rnp->cfg().get_str(CFG_OUTFILE)); + if (!output) { goto done; } @@ -1846,9 +2087,9 @@ result = !rnp_key_export_revocation(keys[0], armored, 0, - cfg.get_cstr(CFG_HASH), - cfg.get_cstr(CFG_REV_TYPE), - cfg.get_cstr(CFG_REV_REASON)); + rnp->cfg().get_cstr(CFG_HASH), + rnp->cfg().get_cstr(CFG_REV_TYPE), + rnp->cfg().get_cstr(CFG_REV_REASON)); done: rnp_output_destroy(armored); rnp_output_destroy(output); @@ -1864,7 +2105,6 @@ ERR_MSG("Key matching '%s' not found.", key); return false; } - rnp_cfg & cfg = cli_rnp_cfg(*rnp); bool res = false; bool revoked = false; rnp_result_t ret = 0; @@ -1877,7 +2117,7 @@ ERR_MSG("Error getting key revocation status."); goto done; } - if (revoked && !cfg.get_bool(CFG_FORCE)) { + if (revoked && !rnp->cfg().get_bool(CFG_FORCE)) { ERR_MSG("Error: key '%s' is revoked already. Use --force to generate another " "revocation signature.", key); @@ -1886,9 +2126,9 @@ ret = rnp_key_revoke(keys[0], 0, - cfg.get_cstr(CFG_HASH), - cfg.get_cstr(CFG_REV_TYPE), - cfg.get_cstr(CFG_REV_REASON)); + rnp->cfg().get_cstr(CFG_HASH), + rnp->cfg().get_cstr(CFG_REV_TYPE), + rnp->cfg().get_cstr(CFG_REV_REASON)); if (ret) { ERR_MSG("Failed to revoke a key: error %d", (int) ret); goto done; @@ -1932,7 +2172,6 @@ ERR_MSG("Key matching '%s' not found.", key); return false; } - rnp_cfg & cfg = cli_rnp_cfg(*rnp); bool res = false; bool secret = false; bool primary = false; @@ -1959,7 +2198,7 @@ flags |= RNP_KEY_REMOVE_SUBKEYS; } - if (secret && !cfg.get_bool(CFG_FORCE)) { + if (secret && !rnp->cfg().get_bool(CFG_FORCE)) { if (!cli_rnp_get_confirmation( rnp, "Key '%s' has corresponding secret key. Do you really want to delete it?", @@ -1983,14 +2222,14 @@ bool cli_rnp_add_key(cli_rnp_t *rnp) { - const std::string &path = cli_rnp_cfg(*rnp).get_str(CFG_KEYFILE); + const std::string &path = rnp->cfg().get_str(CFG_KEYFILE); if (path.empty()) { return false; } - rnp_input_t input = NULL; - if (rnp_input_from_path(&input, path.c_str())) { - ERR_MSG("failed to open key file %s", path.c_str()); + rnp_input_t input = cli_rnp_input_from_specifier(*rnp, path, NULL); + if (!input) { + ERR_MSG("failed to open key from %s", path.c_str()); return false; } @@ -1999,8 +2238,8 @@ rnp_input_destroy(input); // set default key if we didn't have one - if (res && cli_rnp_defkey(rnp).empty()) { - cli_rnp_set_default_key(rnp); + if (res && rnp->defkey().empty()) { + rnp->set_defkey(); } return res; } @@ -2054,35 +2293,17 @@ return path.substr(lpos + 1); } -/* TODO: replace temporary stub with C++ function */ -static bool -adjust_output_path(std::string &path, bool overwrite, cli_rnp_t *rnp) -{ - char pathbuf[PATH_MAX] = {0}; - - if (!rnp_get_output_filename(path.c_str(), pathbuf, sizeof(pathbuf), overwrite, rnp)) { - return false; - } - - path = pathbuf; - return true; -} - static bool cli_rnp_init_io(const std::string &op, rnp_input_t * input, rnp_output_t * output, cli_rnp_t * rnp) { - rnp_cfg & cfg = cli_rnp_cfg(*rnp); - const std::string &in = cfg.get_str(CFG_INFILE); - bool is_stdin = in.empty() || (in == "-"); + const std::string &in = rnp->cfg().get_str(CFG_INFILE); + bool is_pathin = true; if (input) { - rnp_result_t res = is_stdin ? - rnp_input_from_callback(input, stdin_reader, NULL, NULL) : - rnp_input_from_path(input, in.c_str()); - - if (res) { + *input = cli_rnp_input_from_specifier(*rnp, in, &is_pathin); + if (!*input) { return false; } } @@ -2090,34 +2311,22 @@ if (!output) { return true; } - std::string out = cfg.get_str(CFG_OUTFILE); - bool is_stdout = out.empty() || (out == "-"); - bool discard = (op == "verify") && out.empty() && cfg.get_bool(CFG_NO_OUTPUT); + std::string out = rnp->cfg().get_str(CFG_OUTFILE); + bool discard = (op == "verify") && out.empty() && rnp->cfg().get_bool(CFG_NO_OUTPUT); - if (is_stdout && !is_stdin && !discard) { - std::string ext = output_extension(cfg, op); + if (out.empty() && is_pathin && !discard) { + std::string ext = output_extension(rnp->cfg(), op); if (!ext.empty()) { out = in + ext; - is_stdout = false; } } - rnp_result_t res = RNP_ERROR_GENERIC; - if (discard) { - res = rnp_output_to_null(output); - } else if (is_stdout) { - res = rnp_output_to_callback(output, stdout_writer, NULL, NULL); - } else if (!adjust_output_path(out, cfg.get_bool(CFG_OVERWRITE), rnp)) { - ERR_MSG("Operation failed: file '%s' already exists.", out.c_str()); - res = RNP_ERROR_BAD_PARAMETERS; - } else { - res = rnp_output_to_file(output, out.c_str(), RNP_OUTPUT_FILE_OVERWRITE); - } - - if (res && input) { + *output = cli_rnp_output_to_specifier(*rnp, out, discard); + if (!*output && input) { rnp_input_destroy(*input); + *input = NULL; } - return !res; + return *output; } bool @@ -2127,17 +2336,16 @@ rnp_output_t output = NULL; uint32_t flags = 0; uint32_t jflags = 0; - rnp_cfg & cfg = cli_rnp_cfg(*rnp); - if (cfg.get_bool(CFG_GRIPS)) { + if (rnp->cfg().get_bool(CFG_GRIPS)) { flags |= RNP_DUMP_GRIP; jflags |= RNP_JSON_DUMP_GRIP; } - if (cfg.get_bool(CFG_MPIS)) { + if (rnp->cfg().get_bool(CFG_MPIS)) { flags |= RNP_DUMP_MPI; jflags |= RNP_JSON_DUMP_MPI; } - if (cfg.get_bool(CFG_RAW)) { + if (rnp->cfg().get_bool(CFG_RAW)) { flags |= RNP_DUMP_RAW; jflags |= RNP_JSON_DUMP_RAW; } @@ -2149,7 +2357,7 @@ goto done; } - if (cfg.get_bool(CFG_JSON)) { + if (rnp->cfg().get_bool(CFG_JSON)) { char *json = NULL; ret = rnp_dump_packets_to_json(input, jflags, &json); if (!ret) { @@ -2187,8 +2395,7 @@ ERR_MSG("failed to open source or create output"); return false; } - rnp_result_t ret = - rnp_enarmor(input, output, cli_rnp_cfg(*rnp).get_cstr(CFG_ARMOR_DATA_TYPE)); + rnp_result_t ret = rnp_enarmor(input, output, rnp->cfg().get_cstr(CFG_ARMOR_DATA_TYPE)); rnp_input_destroy(input); rnp_output_destroy(output); return !ret; @@ -2257,10 +2464,10 @@ if (rnp_op_sign_set_hash(op, cfg.get_hashalg().c_str())) { goto done; } - rnp_op_sign_set_creation_time(op, get_creation(cfg.get_cstr(CFG_CREATION))); + rnp_op_sign_set_creation_time(op, cfg.get_sig_creation()); { uint32_t expiration = 0; - if (!get_expiration(cfg.get_cstr(CFG_EXPIRATION), &expiration)) { + if (cfg.get_expiration(CFG_EXPIRATION, expiration)) { rnp_op_sign_set_expiration_time(op, expiration); } } @@ -2371,9 +2578,9 @@ /* adding signatures if encrypt-and-sign is used */ if (cfg.get_bool(CFG_SIGN_NEEDED)) { - rnp_op_encrypt_set_creation_time(op, get_creation(cfg.get_cstr(CFG_CREATION))); + rnp_op_encrypt_set_creation_time(op, cfg.get_sig_creation()); uint32_t expiration; - if (!get_expiration(cfg.get_cstr(CFG_EXPIRATION), &expiration)) { + if (cfg.get_expiration(CFG_EXPIRATION, expiration)) { rnp_op_encrypt_set_expiration_time(op, expiration); } @@ -2412,14 +2619,14 @@ cli_rnp_setup(cli_rnp_t *rnp) { /* unset CFG_PASSWD and empty CFG_PASSWD are different cases */ - if (cli_rnp_cfg(*rnp).has(CFG_PASSWD)) { - const std::string &passwd = cli_rnp_cfg(*rnp).get_str(CFG_PASSWD); + if (rnp->cfg().has(CFG_PASSWD)) { + const std::string &passwd = rnp->cfg().get_str(CFG_PASSWD); if (rnp_ffi_set_pass_provider( rnp->ffi, ffi_pass_callback_string, (void *) passwd.c_str())) { return false; } } - rnp->pswdtries = cli_rnp_cfg(*rnp).get_pswdtries(); + rnp->pswdtries = rnp->cfg().get_pswdtries(); return true; } @@ -2434,14 +2641,13 @@ return false; } - rnp_cfg &cfg = cli_rnp_cfg(*rnp); - bool res = false; - bool sign = cfg.get_bool(CFG_SIGN_NEEDED); - bool encrypt = cfg.get_bool(CFG_ENCRYPT_PK) || cfg.get_bool(CFG_ENCRYPT_SK); + bool res = false; + bool sign = rnp->cfg().get_bool(CFG_SIGN_NEEDED); + bool encrypt = rnp->cfg().get_bool(CFG_ENCRYPT_PK) || rnp->cfg().get_bool(CFG_ENCRYPT_SK); if (sign && !encrypt) { - res = cli_rnp_sign(cfg, rnp, input, output); + res = cli_rnp_sign(rnp->cfg(), rnp, input, output); } else if (encrypt) { - res = cli_rnp_encrypt_and_sign(cfg, rnp, input, output); + res = cli_rnp_encrypt_and_sign(rnp->cfg(), rnp, input, output); } else { ERR_MSG("No operation specified"); } @@ -2598,7 +2804,7 @@ if (rnp_casecmp(contents, "signature")) { /* detached signature */ - std::string in = cli_rnp_cfg(*rnp).get_str(CFG_INFILE); + std::string in = rnp->cfg().get_str(CFG_INFILE); if (in.empty() || in == "-") { ERR_MSG("Cannot verify detached signature from stdin."); goto done; @@ -2656,3 +2862,48 @@ rnp_op_verify_destroy(verify); return res; } + +void +cli_rnp_print_praise(void) +{ + printf("%s\n%s\n", PACKAGE_STRING, PACKAGE_BUGREPORT); + printf("Backend: %s\n", rnp_backend_string()); + printf("Backend version: %s\n", rnp_backend_version()); + printf("Supported algorithms:\n"); + cli_rnp_print_feature(stdout, RNP_FEATURE_PK_ALG, "Public key"); + cli_rnp_print_feature(stdout, RNP_FEATURE_SYMM_ALG, "Encryption"); + cli_rnp_print_feature(stdout, RNP_FEATURE_AEAD_ALG, "AEAD"); + cli_rnp_print_feature(stdout, RNP_FEATURE_PROT_MODE, "Key protection"); + cli_rnp_print_feature(stdout, RNP_FEATURE_HASH_ALG, "Hash"); + cli_rnp_print_feature(stdout, RNP_FEATURE_COMP_ALG, "Compression"); + cli_rnp_print_feature(stdout, RNP_FEATURE_CURVE, "Curves"); + printf("Please report security issues at (https://www.rnpgp.org/feedback) and\n" + "general bugs at https://github.com/rnpgp/rnp/issues.\n"); +} + +void +cli_rnp_print_feature(FILE *fp, const char *type, const char *printed_type) +{ + char * result = NULL; + size_t count; + if (rnp_supported_features(type, &result) != RNP_SUCCESS) { + ERR_MSG("Failed to list supported features: %s", type); + return; + } + json_object *jso = json_tokener_parse(result); + if (!jso) { + ERR_MSG("Failed to parse JSON with features: %s", type); + goto done; + } + fprintf(fp, "%s: ", printed_type); + count = json_object_array_length(jso); + for (size_t idx = 0; idx < count; idx++) { + json_object *val = json_object_array_get_idx(jso, idx); + fprintf(fp, " %s%s", json_object_get_string(val), idx < count - 1 ? "," : ""); + } + fputs("\n", fp); + fflush(fp); + json_object_put(jso); +done: + rnp_buffer_destroy(result); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/fficli.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/fficli.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/fficli.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/fficli.h 2022-04-15 07:49:22.000000000 +0000 @@ -36,15 +36,72 @@ #include "rnpcfg.h" #include "json.h" -typedef struct cli_rnp_t { +class cli_rnp_t { + private: + rnp_cfg cfg_{}; + bool load_keyring(bool secret); + bool is_cv25519_subkey(rnp_key_handle_t handle); + bool get_protection(rnp_key_handle_t handle, + std::string & hash, + std::string & cipher, + size_t & iterations); + bool check_cv25519_bits(rnp_key_handle_t key, char *prot_password, bool &tweaked); + + public: rnp_ffi_t ffi{}; - rnp_cfg cfg{}; FILE * resfp{}; /* where to put result messages, defaults to stdout */ FILE * passfp{}; /* file pointer for password input */ FILE * userio_in{}; /* file pointer for user's inputs */ FILE * userio_out{}; /* file pointer for user's outputs */ int pswdtries{}; /* number of password tries, -1 for unlimited */ -} cli_rnp_t; + + bool init(const rnp_cfg &cfg); + void end(); + + bool load_keyrings(bool loadsecret = false); + + const std::string & + defkey() + { + return cfg_.get_str(CFG_KR_DEF_KEY); + } + + void set_defkey(); + + const std::string & + pubpath() + { + return cfg_.get_str(CFG_KR_PUB_PATH); + } + + const std::string & + secpath() + { + return cfg_.get_str(CFG_KR_SEC_PATH); + } + + const std::string & + pubformat() + { + return cfg_.get_str(CFG_KR_PUB_FORMAT); + } + + const std::string & + secformat() + { + return cfg_.get_str(CFG_KR_SEC_FORMAT); + } + + rnp_cfg & + cfg() + { + return cfg_; + } + + bool fix_cv25519_subkey(const std::string &key, bool checkonly = false); + + bool edit_key(const std::string &key); +}; typedef enum cli_search_flags_t { CLI_SEARCH_SECRET = 1 << 0, /* search secret keys only */ @@ -65,19 +122,37 @@ */ bool cli_cfg_set_keystore_info(rnp_cfg &cfg); -rnp_cfg & cli_rnp_cfg(cli_rnp_t &rnp); -const std::string cli_rnp_defkey(cli_rnp_t *rnp); -const std::string cli_rnp_pubpath(cli_rnp_t *rnp); -const std::string cli_rnp_secpath(cli_rnp_t *rnp); -const std::string cli_rnp_pubformat(cli_rnp_t *rnp); -const std::string cli_rnp_secformat(cli_rnp_t *rnp); - -bool cli_rnp_init(cli_rnp_t *, const rnp_cfg &); -bool cli_rnp_baseinit(cli_rnp_t *); -void cli_rnp_end(cli_rnp_t *); -bool cli_rnp_load_keyrings(cli_rnp_t *rnp, bool loadsecret); +/** + * @brief Create input object from the specifier, which may represent: + * - path + * - stdin (if `-` or empty string is passed) + * - environment variable contents, if path looks like `env:VARIABLE_NAME` + * @param rnp initialized CLI rnp object + * @param spec specifier + * @param is_path optional parameter. If specifier is path (not stdin, env variable), then true + * will be stored here, false otherwise. May be NULL if this information is not + * needed. + * @return rnp_input_t object or NULL if operation failed. + */ +rnp_input_t cli_rnp_input_from_specifier(cli_rnp_t & rnp, + const std::string &spec, + bool * is_path); + +/** + * @brief Create output object from the specifier, which may represent: + * - path + * - stdout (if `-` or empty string is passed) + * + * @param rnp initialized CLI rnp object + * @param spec specifier + * @param discard just discard output + * @return rnp_output_t or NULL if operation failed. + */ +rnp_output_t cli_rnp_output_to_specifier(cli_rnp_t & rnp, + const std::string &spec, + bool discard = false); + bool cli_rnp_save_keyrings(cli_rnp_t *rnp); -void cli_rnp_set_default_key(cli_rnp_t *rnp); void cli_rnp_print_key_info( FILE *fp, rnp_ffi_t ffi, rnp_key_handle_t key, bool psecret, bool psigs); bool cli_rnp_set_generate_params(rnp_cfg &cfg); @@ -130,6 +205,17 @@ bool cli_rnp_protect_file(cli_rnp_t *rnp); bool cli_rnp_process_file(cli_rnp_t *rnp); std::string cli_rnp_escape_string(const std::string &src); +void cli_rnp_print_praise(void); +void cli_rnp_print_feature(FILE *fp, const char *type, const char *printed_type); +/** + * @brief Convert algorithm name representation to one used by FFI. + * I.e. aes-128 to AES128, 3DES to TRIPLEDES, SHA-1 to SHA1 and so on. + * + * @param alg algorithm string + * @return string with FFI algorithm's name. In case alias is not found the source string will + * be returned. + */ +const std::string cli_rnp_alg_to_ffi(const std::string alg); void clear_key_handles(std::vector &keys); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnp.1.adoc thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnp.1.adoc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnp.1.adoc 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnp.1.adoc 2022-04-15 07:49:22.000000000 +0000 @@ -27,11 +27,16 @@ By default, *rnp* will apply a _COMMAND_, additionally configured with _OPTIONS_, to all _INPUT_FILE_(s) or _stdin_ if no _INPUT_FILE_ is given. +There are some special cases for _INPUT_FILE_ : + +* _-_ (dash) substitutes to _stdin_ +* env:VARIABLE_NAME substitutes to the contents of environment variable VARIABLE_NAME Depending on the input, output may be written: -* to the specified file with a removed or added file extension (_.pgp_, _.asc_, _.sig_); or -* to _stdout_. +* if *--output* option is given output is written to the path specified (or to the *stdout* if *-* is used) +* to the _INPUT_FILE_ with a removed or added file extension (_.pgp_, _.asc_, _.sig_); or +* to the _stdout_ if input was read from the _stdin_. Without the *--armor* option, output will be in binary. @@ -67,8 +72,8 @@ *--cipher*::: Select a specific cipher. -*-z*, *--zip*, *--bzip*::: -Select a compression algorithm. +*-z 0..9*, *--zlib*, *--zip*, *--bzip*::: +Select a compression algorithm and level. *--armor*::: Output ASCII data instead of binary via the *--armor* option. If the input file is _file.ext_, and *--output* is not specified, then the data will be written (depending on *--armor* option) to _file.ext.pgp_ or _file.ext.asc_. + @@ -129,7 +134,7 @@ Depending on encryption options, you may be asked for the password of one of your secret keys, or for the encryption password. These options override that behavior such that you can input the password through automated means. *-v*, *--verify*:: -Verify signature(s) without writing embedded data out, if any. + +Verify signature(s) without writing embedded data out, if any (unless option _--output_ is specified). + + To verify the detached signature of a file _file.ext_, the detached signature file in the file name pattern of _file.ext.sig_ or _file.ext.asc_ must exist. + + @@ -298,9 +303,12 @@ + This option allows the auto-detection behavior to be overridden. -*--debug* _FILENAME.CPP_:: -Enable debug output for the source file specified. For development use only. - +*--notty*:: +Disable use of tty. + ++ +By default RNP would detect whether TTY is attached and use it for user prompts. + ++ +This option overrides default behaviour so user input may be passed in batch mode. == EXIT STATUS @@ -353,6 +361,11 @@ Additionally, the message will be signed with key _0x44616E69656C2057_. +=== EXAMPLE 5 + +*printf* _"Message"_ | *rnp* *--keyfile* _env:PGP_ENCRYPTION_KEY_ *-e* *-* *--armor* + +Encrypt message, passed via stdin, using the key, stored in environment variable *PGP_ENCRYPTION_KEY*, add ascii armoring, and print result to the stdout. == BUGS diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnpcfg.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnpcfg.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnpcfg.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnpcfg.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -41,7 +41,7 @@ #include "rnpcfg.h" #include "defaults.h" -#include "logging.h" +#include "utils.h" #include "time-utils.h" #include @@ -187,8 +187,7 @@ RNP_LOG("expected list val for \"%s\"", key.c_str()); throw std::invalid_argument("type"); } - rnp_cfg_list_val *list = dynamic_cast(vals_[key]); - list->val().push_back(val); + (dynamic_cast(*vals_[key])).val().push_back(val); } bool @@ -203,7 +202,7 @@ if (!has(key) || (vals_.at(key)->type() != RNP_CFG_VAL_STRING)) { return empty_str_; } - return (dynamic_cast(vals_.at(key)))->val(); + return (dynamic_cast(*vals_.at(key))).val(); } const char * @@ -212,7 +211,7 @@ if (!has(key) || (vals_.at(key)->type() != RNP_CFG_VAL_STRING)) { return NULL; } - return (dynamic_cast(vals_.at(key)))->val().c_str(); + return (dynamic_cast(*vals_.at(key))).val().c_str(); } int @@ -224,11 +223,11 @@ const rnp_cfg_val *val = vals_.at(key); switch (val->type()) { case RNP_CFG_VAL_INT: - return (dynamic_cast(val))->val(); + return (dynamic_cast(*val)).val(); case RNP_CFG_VAL_BOOL: - return (dynamic_cast(val))->val(); + return (dynamic_cast(*val)).val(); case RNP_CFG_VAL_STRING: - return atoi((dynamic_cast(val))->val().c_str()); + return atoi((dynamic_cast(*val)).val().c_str()); default: return def; } @@ -243,11 +242,11 @@ const rnp_cfg_val *val = vals_.at(key); switch (val->type()) { case RNP_CFG_VAL_INT: - return (dynamic_cast(val))->val(); + return (dynamic_cast(*val)).val(); case RNP_CFG_VAL_BOOL: - return (dynamic_cast(val))->val(); + return (dynamic_cast(*val)).val(); case RNP_CFG_VAL_STRING: { - const std::string &str = (dynamic_cast(val))->val(); + const std::string &str = (dynamic_cast(*val)).val(); return !strcasecmp(str.c_str(), "true") || (atoi(str.c_str()) > 0); } default: @@ -261,8 +260,7 @@ if (!has(key) || (vals_.at(key)->type() != RNP_CFG_VAL_LIST)) { return 0; } - const rnp_cfg_list_val *val = dynamic_cast(vals_.at(key)); - return val->val().size(); + return (dynamic_cast(*vals_.at(key))).val().size(); } const std::string & @@ -272,8 +270,7 @@ RNP_LOG("idx is out of bounds for \"%s\"", key.c_str()); throw std::invalid_argument("idx"); } - const rnp_cfg_list_val *val = dynamic_cast(vals_.at(key)); - return val->val().at(idx); + return (dynamic_cast(*vals_.at(key))).val().at(idx); } std::vector @@ -287,8 +284,7 @@ RNP_LOG("no list at the key \"%s\"", key.c_str()); throw std::invalid_argument("key"); } - const rnp_cfg_list_val *val = dynamic_cast(vals_.at(key)); - return val->val(); + return (dynamic_cast(*vals_.at(key))).val(); } int @@ -314,6 +310,109 @@ return DEFAULT_HASH_ALG; } +bool +rnp_cfg::get_expiration(const std::string &key, uint32_t &seconds) const +{ + if (!has(key)) { + return false; + } + const std::string &val = get_str(key); + uint64_t delta; + uint64_t t; + if (parse_date(val, t)) { + uint64_t now = time(NULL); + if (t > now) { + delta = t - now; + if (delta > UINT32_MAX) { + RNP_LOG("Expiration time exceeds 32-bit value"); + return false; + } + seconds = delta; + return true; + } + return false; + } + const char *reg = "^([0-9]+)([hdwmy]?)$"; +#ifndef RNP_USE_STD_REGEX + static regex_t r; + static int compiled; + regmatch_t matches[3]; + + if (!compiled) { + compiled = 1; + if (regcomp(&r, reg, REG_EXTENDED | REG_ICASE)) { + RNP_LOG("failed to compile regexp"); + return false; + } + } + if (regexec(&r, val.c_str(), ARRAY_SIZE(matches), matches, 0)) { + return false; + } + auto delta_str = &val.c_str()[matches[1].rm_so]; + char mult = val.c_str()[matches[2].rm_so]; +#else + static std::regex re(reg, std::regex_constants::extended | std::regex_constants::icase); + std::smatch result; + + if (!std::regex_search(val, result, re)) { + return false; + } + std::string delta_stdstr = result[1].str(); + const char *delta_str = delta_stdstr.c_str(); + char mult = result[2].str()[0]; +#endif + errno = 0; + delta = strtoul(delta_str, NULL, 10); + if (errno || delta > UINT_MAX) { + RNP_LOG("Invalid expiration '%s'.", delta_str); + return false; + } + switch (std::tolower(mult)) { + case 'h': + delta *= 60 * 60; + break; + case 'd': + delta *= 60 * 60 * 24; + break; + case 'w': + delta *= 60 * 60 * 24 * 7; + break; + case 'm': + delta *= 60 * 60 * 24 * 31; + break; + case 'y': + delta *= 60 * 60 * 24 * 365; + break; + } + if (delta > UINT32_MAX) { + RNP_LOG("Expiration value exceed 32 bit."); + return false; + } + seconds = delta; + return true; +} + +uint64_t +rnp_cfg::get_sig_creation() const +{ + if (!has(CFG_CREATION)) { + return time(NULL); + } + const std::string &cr = get_str(CFG_CREATION); + /* Check if string is date */ + uint64_t t; + if (parse_date(cr, t)) { + return t; + } + /* Check if string is UNIX timestamp */ + for (auto c : cr) { + if (!isdigit(c)) { + return time(NULL); + } + } + return std::stoll(cr); +} + void rnp_cfg::copy(const rnp_cfg &src) { @@ -324,16 +423,16 @@ rnp_cfg_val *val = NULL; switch (it.second->type()) { case RNP_CFG_VAL_INT: - val = new rnp_cfg_int_val(*(dynamic_cast(it.second))); + val = new rnp_cfg_int_val(dynamic_cast(*it.second)); break; case RNP_CFG_VAL_BOOL: - val = new rnp_cfg_bool_val(*(dynamic_cast(it.second))); + val = new rnp_cfg_bool_val(dynamic_cast(*it.second)); break; case RNP_CFG_VAL_STRING: - val = new rnp_cfg_str_val(*(dynamic_cast(it.second))); + val = new rnp_cfg_str_val(dynamic_cast(*it.second)); break; case RNP_CFG_VAL_LIST: - val = new rnp_cfg_list_val(*(dynamic_cast(it.second))); + val = new rnp_cfg_list_val(dynamic_cast(*it.second)); break; default: continue; @@ -389,27 +488,8 @@ } } -/** - * @brief Grabs date from the string in %Y-%m-%d format - * - * @param s [in] NULL-terminated string with the date - * @param t [out] On successful return result will be placed here - * @return true on success or false otherwise - */ - -/** @brief - * - * @param s [in] NULL-terminated string with the date - * @param t [out] UNIX timestamp of - * successfully parsed date - * @return 0 when parsed successfully - * 1 when s doesn't match the regex - * -1 when - * s matches the regex but the date is not acceptable - * -2 failure - */ -static int -grabdate(const char *s, uint64_t *t) +bool +rnp_cfg::parse_date(const std::string &s, uint64_t &t) const { /* fill time zone information */ const time_t now = time(NULL); @@ -417,45 +497,45 @@ tm.tm_hour = 0; tm.tm_min = 0; tm.tm_sec = 0; + const char *reg = "^([0-9]{4})[-/\\.]([0-9]{2})[-/\\.]([0-9]{2})$"; #ifndef RNP_USE_STD_REGEX static regex_t r; static int compiled; - regmatch_t matches[10]; if (!compiled) { compiled = 1; - if (regcomp(&r, - "^([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])$", - REG_EXTENDED) != 0) { + if (regcomp(&r, reg, REG_EXTENDED)) { RNP_LOG("failed to compile regexp"); - return -2; + return false; } } - if (regexec(&r, s, 10, matches, 0) != 0) { - return 1; + regmatch_t matches[4]; + if (regexec(&r, s.c_str(), ARRAY_SIZE(matches), matches, 0)) { + return false; } - int year = (int) strtol(&s[(int) matches[1].rm_so], NULL, 10); - int mon = (int) strtol(&s[(int) matches[2].rm_so], NULL, 10); - int mday = (int) strtol(&s[(int) matches[3].rm_so], NULL, 10); + int year = strtol(&s[matches[1].rm_so], NULL, 10); + int mon = strtol(&s[matches[2].rm_so], NULL, 10); + int mday = strtol(&s[matches[3].rm_so], NULL, 10); #else - static std::regex re("^([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])$", - std::regex_constants::ECMAScript); + static std::regex re(reg, std::regex_constants::extended); std::smatch result; - std::string input = s; - if (!std::regex_search(input, result, re)) { - return 1; + if (!std::regex_search(s, result, re)) { + return false; } - int year = (int) strtol(result[1].str().c_str(), NULL, 10); - int mon = (int) strtol(result[2].str().c_str(), NULL, 10); - int mday = (int) strtol(result[3].str().c_str(), NULL, 10); + int year = std::stoi(result[1].str()); + int mon = std::stoi(result[2].str()); + int mday = std::stoi(result[3].str()); #endif if (year < 1970 || mon < 1 || mon > 12 || !mday || (mday > days_in_month(year, mon))) { - return -1; + RNP_LOG("invalid date: %s.", s.c_str()); + return false; } tm.tm_year = year - 1900; tm.tm_mon = mon - 1; tm.tm_mday = mday; + /* line below is required to correctly handle DST changes */ + tm.tm_isdst = -1; struct tm check_tm = tm; time_t built_time = rnp_mktime(&tm); @@ -465,104 +545,8 @@ * timestamp */ RNP_LOG("Warning: date %s is beyond of 32-bit time_t, so timestamp was reduced to " "maximum supported value.", - s); - } - *t = built_time; - return 0; -} - -int -get_expiration(const char *s, uint32_t *res) -{ - if (!s || !strlen(s)) { - return -1; - } - uint64_t delta; - uint64_t t; - int grabdate_result = grabdate(s, &t); - if (!grabdate_result) { - uint64_t now = time(NULL); - if (t > now) { - delta = t - now; - if (delta > UINT32_MAX) { - return -3; - } - *res = delta; - return 0; - } - return -2; - } else if (grabdate_result < 0) { - return -2; - } -#ifndef RNP_USE_STD_REGEX - static regex_t r; - static int compiled; - regmatch_t matches[10]; - - if (!compiled) { - compiled = 1; - if (regcomp(&r, "^([0-9]+)([hdwmy]?)$", REG_EXTENDED | REG_ICASE) != 0) { - RNP_LOG("failed to compile regexp"); - return -2; - } - } - if (regexec(&r, s, 10, matches, 0) != 0) { - return -2; - } - auto delta_str = &s[(int) matches[1].rm_so]; - char mult = s[(int) matches[2].rm_so]; -#else - static std::regex re("^([0-9]+)([hdwmy]?)$", - std::regex_constants::ECMAScript | std::regex_constants::icase); - std::smatch result; - std::string input = s; - - if (!std::regex_search(input, result, re)) { - return -2; - } - std::string delta_stdstr = result[1].str(); - const char *delta_str = delta_stdstr.c_str(); - char mult = result[2].str()[0]; -#endif - errno = 0; - delta = (uint64_t) strtoul(delta_str, NULL, 10); - if (errno || delta > UINT_MAX) { - return -3; - } - switch (std::tolower(mult)) { - case 'h': - delta *= 60 * 60; - break; - case 'd': - delta *= 60 * 60 * 24; - break; - case 'w': - delta *= 60 * 60 * 24 * 7; - break; - case 'm': - delta *= 60 * 60 * 24 * 31; - break; - case 'y': - delta *= 60 * 60 * 24 * 365; - break; - } - if (delta > UINT32_MAX) { - return -4; - } - *res = delta; - return 0; -} - -int64_t -get_creation(const char *s) -{ - uint64_t t; - - if (!s || !strlen(s)) { - return time(NULL); - } - if (!grabdate(s, &t)) { - return t; + s.c_str()); } - return (uint64_t) strtoll(s, NULL, 10); + t = built_time; + return true; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnpcfg.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnpcfg.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnpcfg.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnpcfg.h 2022-04-15 07:49:22.000000000 +0000 @@ -50,7 +50,6 @@ #define CFG_USERID "userid" /* userid for the ongoing operation */ #define CFG_RECIPIENTS "recipients" /* list of encrypted data recipients */ #define CFG_SIGNERS "signers" /* list of signers */ -#define CFG_VERBOSE "verbose" /* verbose logging */ #define CFG_HOMEDIR "homedir" /* home directory - folder with keyrings and so on */ #define CFG_KEYFILE "keyfile" /* path to the file with key(s), used instead of keyring */ #define CFG_PASSFD "pass-fd" /* password file descriptor */ @@ -68,7 +67,6 @@ #define CFG_ENCRYPT_SK "encrypt_sk" /* password encryption should be used */ #define CFG_IO_RESS "ress" /* results stream */ #define CFG_NUMBITS "numbits" /* number of bits in generated key */ -#define CFG_KEYFORMAT "format" /* key format : "human" for human-readable or ... */ #define CFG_EXPERT "expert" /* expert key generation mode */ #define CFG_ZLEVEL "zlevel" /* compression level: 0..9 (0 for no compression) */ #define CFG_ZALG "zalg" /* compression algorithm: zip, zlib or bzip2 */ @@ -86,6 +84,9 @@ #define CFG_REV_TYPE "rev-type" /* revocation reason code */ #define CFG_REV_REASON "rev-reason" /* revocation reason human-readable string */ #define CFG_PERMISSIVE "permissive" /* ignore bad packets during key import */ +#define CFG_NOTTY "notty" /* disable tty usage and do input/output via stdin/stdout */ +#define CFG_FIX_25519_BITS "fix-25519-bits" /* fix Cv25519 secret key via --edit-key */ +#define CFG_CHK_25519_BITS "check-25519-bits" /* check Cv25519 secret key bits */ /* rnp keyring setup variables */ #define CFG_KR_PUB_FORMAT "kr-pub-format" @@ -117,6 +118,15 @@ std::unordered_map vals_; std::string empty_str_; + /** @brief Parse date from the string in %Y-%m-%d format (using "-", "/", "." as a + * separator) + * + * @param s string with the date + * @param t UNIX timestamp of successfully parsed date + * @return true when parsed successfully or false otherwise + */ + bool parse_date(const std::string &s, uint64_t &t) const; + public: /** @brief load default settings */ void load_defaults(); @@ -155,6 +165,29 @@ int get_pswdtries() const; /** @brief get hash algorithm */ const std::string get_hashalg() const; + + /** @brief Get expiration time from the cfg variable, as value relative to the current + * time. As per OpenPGP standard it should fit in 32 bit value, otherwise error is + * returned. + * + * Expiration may be specified in different formats: + * - 10d : 10 days (you can use [h]ours, d[ays], [w]eeks, [m]onthes) + * - 2017-07-12 : as the exact date + * - 60000 : number of seconds + * + * @param seconds On successfull return result will be placed here + * @return true on success or false otherwise + */ + bool get_expiration(const std::string &key, uint32_t &seconds) const; + + /** @brief Get signature creation time from the config. + * Creation time may be specified in different formats: + * - 2017-07-12 : as the exact date + * - 1499334073 : timestamp + * + * @return timestamp of the signature creation. + */ + uint64_t get_sig_creation() const; /** @brief copy or override a configuration. * @param src vals will be overridden (if key exist) or copied (if not) from this object */ @@ -167,33 +200,4 @@ ~rnp_cfg(); }; -/* rnp CLI helper functions */ - -/** @brief Get signature validity expiration time from the user input - * - * Signature expiration may be specified in different formats: - * - 10d : 10 days (you can use [h]ours, d[ays], [w]eeks, [m]onthes) - * - 2017-07-12 : as the exact date when signature becomes invalid - * - 60000 : number of seconds - * - * @param s [in] NULL-terminated string with the date - * @param t [out] On successfull return result will be placed here - * @return 0 on success - * -1 on parse error - * -2 if a date in the past was specified - * -3 overflow - */ -int get_expiration(const char *s, uint32_t *t); - -/** @brief Get signature validity start time from the user input - * - * Signature validity may be specified in different formats: - * - 2017-07-12 : as the exact date when signature becomes invalid - * - 1499334073 : timestamp - * - * @param s [in] NULL-terminated string with the date - * @return timestamp of the validity start - */ -int64_t get_creation(const char *s); - #endif diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnp.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnp.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnp/rnp.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnp/rnp.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2017-2021 [Ribose Inc](https://www.ribose.com). * Copyright (c) 2009 The NetBSD Foundation, Inc. * All rights reserved. * @@ -51,46 +51,47 @@ #include "fficli.h" #include "logging.h" -#ifndef RNP_USE_STD_REGEX -#include -#else -#include -#endif - -static const char *rnp_prog_name = NULL; - -static const char *usage = "-h, --help OR\n" - "\t--encrypt [--output=file] [options] files... OR\n" - "\t-c, --symmetric [--output=file] [options] files...OR\n" - "\t--decrypt [--output=file] [options] files... OR\n" - "\t--sign [--detach] [--hash=alg] [--output=file]\n" - "\t\t[options] files... OR\n" - "\t--verify [options] files... OR\n" - "\t--cat [--output=file] [options] files... OR\n" - "\t--clearsign [--output=file] [options] files... OR\n" - "\t--list-packets [options] OR\n" - "\t--dearmor [--output=file] file OR\n" - "\t--enarmor= OR\n" - "\t--list-packets [--json] [--grips] [--mpi] [--raw] OR\n" - "\t\t[--output=file] file OR\n" - "\t--version\n" - "where options are:\n" - "\t[-r, --recipient] AND/OR\n" - "\t[--passwords] AND/OR\n" - "\t[--armor] AND/OR\n" - "\t[--cipher=] AND/OR\n" - "\t[--zip, --zlib, --bzip, -z 0..9] AND/OR\n" - "\t[--aead[=EAX, OCB]] AND/OR\n" - "\t[--aead-chunk-bits=0..56] AND/OR\n" - "\t[--coredumps] AND/OR\n" - "\t[--homedir=] AND/OR\n" - "\t[-f, --keyfile=] AND/OR\n" - "\t[--keystore-format=] AND/OR\n" - "\t[--numtries=] AND/OR\n" - "\t[-u, --userid=] AND/OR\n" - "\t[--maxmemalloc=] AND/OR\n" - "\t[--verbose]\n"; +static const char *usage = + "Sign, verify, encrypt, decrypt, investigate OpenPGP data.\n" + "Usage: rnp --command [options] [files]\n" + "Commands:\n" + " -h, --help This help message.\n" + " -V, --version Print RNP version information.\n" + " -e, --encrypt Encrypt data using the public key(s).\n" + " -r, --recipient Specify recipient's key via uid/keyid/fingerprint.\n" + " --cipher name Specify symmetric cipher, used for encryption.\n" + " --aead[=EAX, OCB] Use AEAD for encryption.\n" + " -z 0..9 Set the compression level.\n" + " --[zip,zlib,bzip] Use the corresponding compression algorithm.\n" + " --armor Apply ASCII armor to the encryption/signing output.\n" + " -c, --symmetric Encrypt data using the password(s).\n" + " --passwords num Encrypt to the specified number of passwords.\n" + " -s, --sign Sign data. May be combined with encryption.\n" + " --detach Produce detached signature.\n" + " -u, --userid Specify signing key(s) via uid/keyid/fingerprint.\n" + " --hash Specify hash algorithm, used during signing.\n" + " --clearsign Cleartext-sign data.\n" + " -d, --decrypt Decrypt and output data, verifying signatures.\n" + " -v, --verify Verify signatures, without outputting data.\n" + " --dearmor Strip ASCII armor from the data, outputting binary.\n" + " --enarmor Add ASCII armor to the data.\n" + " --list-packets List OpenPGP packets from the input.\n" + " --json Use JSON output instead of human-readable.\n" + " --grips Dump key fingerprints and grips.\n" + " --mpi Dump MPI values from packets.\n" + " --raw Dump raw packet contents as well.\n" + "\n" + "Other options:\n" + " --homedir path Override home directory (default is ~/.rnp/).\n" + " -f, --keyfile Load key(s) only from the file specified.\n" + " --output [file, -] Write data to the specified file or stdout.\n" + " --overwrite Overwrite output file without a prompt.\n" + " --password Password used during operation.\n" + " --pass-fd num Read password(s) from the file descriptor.\n" + " --notty Do not output anything to the TTY.\n" + "\n" + "See man page for a detailed listing and explanation.\n" + "\n"; enum optdefs { /* Commands as they are get via CLI */ @@ -121,7 +122,6 @@ OPT_HASH_ALG, OPT_OUTPUT, OPT_RESULTS, - OPT_VERBOSE, OPT_COREDUMPS, OPT_PASSWDFD, OPT_PASSWD, @@ -142,6 +142,7 @@ OPT_GRIPS, OPT_MPIS, OPT_RAW, + OPT_NOTTY, /* debug */ OPT_DEBUG @@ -156,11 +157,7 @@ {"sign", no_argument, NULL, CMD_SIGN}, {"clearsign", no_argument, NULL, CMD_CLEARSIGN}, {"verify", no_argument, NULL, CMD_VERIFY}, - {"cat", no_argument, NULL, CMD_VERIFY_CAT}, - {"vericat", no_argument, NULL, CMD_VERIFY_CAT}, {"verify-cat", no_argument, NULL, CMD_VERIFY_CAT}, - {"verify-show", no_argument, NULL, CMD_VERIFY_CAT}, - {"verifyshow", no_argument, NULL, CMD_VERIFY_CAT}, {"symmetric", no_argument, NULL, CMD_SYM_ENCRYPT}, {"dearmor", no_argument, NULL, CMD_DEARMOR}, {"enarmor", required_argument, NULL, CMD_ENARMOR}, @@ -183,10 +180,7 @@ {"armour", no_argument, NULL, OPT_ARMOR}, {"detach", no_argument, NULL, OPT_DETACHED}, {"detached", no_argument, NULL, OPT_DETACHED}, - {"hash-alg", required_argument, NULL, OPT_HASH_ALG}, {"hash", required_argument, NULL, OPT_HASH_ALG}, - {"algorithm", required_argument, NULL, OPT_HASH_ALG}, - {"verbose", no_argument, NULL, OPT_VERBOSE}, {"pass-fd", required_argument, NULL, OPT_PASSWDFD}, {"password", required_argument, NULL, OPT_PASSWD}, {"passwords", required_argument, NULL, OPT_PASSWORDS}, @@ -196,9 +190,7 @@ {"expiration", required_argument, NULL, OPT_EXPIRATION}, {"expiry", required_argument, NULL, OPT_EXPIRATION}, {"cipher", required_argument, NULL, OPT_CIPHER}, - {"num-tries", required_argument, NULL, OPT_NUMTRIES}, {"numtries", required_argument, NULL, OPT_NUMTRIES}, - {"attempts", required_argument, NULL, OPT_NUMTRIES}, {"zip", no_argument, NULL, OPT_ZALG_ZIP}, {"zlib", no_argument, NULL, OPT_ZALG_ZLIB}, {"bzip", no_argument, NULL, OPT_ZALG_BZIP}, @@ -210,24 +202,17 @@ {"grips", no_argument, NULL, OPT_GRIPS}, {"mpi", no_argument, NULL, OPT_MPIS}, {"raw", no_argument, NULL, OPT_RAW}, + {"notty", no_argument, NULL, OPT_NOTTY}, {NULL, 0, NULL, 0}, }; -static void -print_praise(void) -{ - ERR_MSG("%s\nAll bug reports, praise and chocolate, please, to:\n%s", - PACKAGE_STRING, - PACKAGE_BUGREPORT); -} - /* print a usage message */ static void print_usage(const char *usagemsg) { - print_praise(); - ERR_MSG("Usage: %s %s", rnp_prog_name, usagemsg); + cli_rnp_print_praise(); + ERR_MSG("%s", usagemsg); } /* do a command once for a specified config */ @@ -236,7 +221,7 @@ { bool ret = false; - switch (cli_rnp_cfg(*rnp).get_int(CFG_COMMAND)) { + switch (rnp->cfg().get_int(CFG_COMMAND)) { case CMD_PROTECT: ret = cli_rnp_protect_file(rnp); break; @@ -253,7 +238,7 @@ ret = cli_rnp_armor_file(rnp); break; case CMD_VERSION: - print_praise(); + cli_rnp_print_praise(); ret = true; break; default: @@ -287,7 +272,7 @@ break; case CMD_CLEARSIGN: cfg.set_bool(CFG_CLEARTEXT, true); - /* FALLTHROUGH */ + [[fallthrough]]; case CMD_SIGN: cfg.set_bool(CFG_NEEDSSECKEY, true); cfg.set_bool(CFG_SIGN_NEEDED, true); @@ -304,7 +289,7 @@ case CMD_VERIFY: /* single verify will discard output, decrypt will not */ cfg.set_bool(CFG_NO_OUTPUT, true); - /* FALLTHROUGH */ + [[fallthrough]]; case CMD_VERIFY_CAT: newcmd = CMD_PROCESS; break; @@ -372,6 +357,9 @@ return setcmd(cfg, val, arg); /* options */ case OPT_COREDUMPS: +#ifdef _WIN32 + ERR_MSG("warning: --coredumps doesn't make sense on windows systems."); +#endif cfg.set_bool(CFG_COREDUMPS, true); return true; case OPT_KEY_STORE_FORMAT: @@ -401,9 +389,6 @@ case OPT_DETACHED: cfg.set_bool(CFG_DETACHED, true); return true; - case OPT_VERBOSE: - cfg.set_int(CFG_VERBOSE, cfg.get_int(CFG_VERBOSE) + 1); - return true; case OPT_HOMEDIR: if (!arg) { ERR_MSG("No home directory argument provided"); @@ -424,12 +409,14 @@ ERR_MSG("No hash algorithm argument provided"); return false; } - bool supported = false; - if (rnp_supports_feature(RNP_FEATURE_HASH_ALG, arg, &supported) || !supported) { + bool supported = false; + const std::string &alg = cli_rnp_alg_to_ffi(arg); + if (rnp_supports_feature(RNP_FEATURE_HASH_ALG, alg.c_str(), &supported) || + !supported) { ERR_MSG("Unsupported hash algorithm: %s", arg); return false; } - cfg.set_str(CFG_HASH, arg); + cfg.set_str(CFG_HASH, alg); return true; } case OPT_PASSWDFD: @@ -486,12 +473,14 @@ ERR_MSG("No encryption algorithm argument provided"); return false; } - bool supported = false; - if (rnp_supports_feature(RNP_FEATURE_SYMM_ALG, arg, &supported) || !supported) { - ERR_MSG("Warning, unsupported encryption algorithm: %s", arg); - arg = DEFAULT_SYMM_ALG; + bool supported = false; + const std::string &alg = cli_rnp_alg_to_ffi(arg); + if (rnp_supports_feature(RNP_FEATURE_SYMM_ALG, alg.c_str(), &supported) || + !supported) { + ERR_MSG("Unsupported encryption algorithm: %s", arg); + return false; } - cfg.set_str(CFG_CIPHER, arg); + cfg.set_str(CFG_CIPHER, alg); return true; } case OPT_NUMTRIES: @@ -549,8 +538,12 @@ case OPT_RAW: cfg.set_bool(CFG_RAW, true); return true; + case OPT_NOTTY: + cfg.set_bool(CFG_NOTTY, true); + return true; case OPT_DEBUG: - return rnp_enable_debug(arg); + ERR_MSG("Option --debug is deprecated, ignoring."); + return true; default: return setcmd(cfg, CMD_HELP, arg); } @@ -558,65 +551,6 @@ return false; } -/* we have -o option=value -- parse, and process */ -static bool -parse_option(rnp_cfg &cfg, const char *s) -{ -#ifndef RNP_USE_STD_REGEX - static regex_t opt; - struct option *op; - static int compiled; - regmatch_t matches[10]; - char option[128]; - char value[128]; - - if (!compiled) { - compiled = 1; - if (regcomp(&opt, "([^=]{1,128})(=(.*))?", REG_EXTENDED) != 0) { - ERR_MSG("Can't compile regex"); - return 0; - } - } - if (regexec(&opt, s, 10, matches, 0) == 0) { - snprintf(option, - sizeof(option), - "%.*s", - (int) (matches[1].rm_eo - matches[1].rm_so), - &s[matches[1].rm_so]); - if (matches[2].rm_so > 0) { - snprintf(value, - sizeof(value), - "%.*s", - (int) (matches[3].rm_eo - matches[3].rm_so), - &s[matches[3].rm_so]); - } else { - value[0] = 0x0; - } - for (op = options; op->name; op++) { - if (strcmp(op->name, option) == 0) - return setoption(cfg, op->val, value); - } - } -#else - static std::regex re("([^=]{1,128})(=(.*))?", std::regex_constants::extended); - std::string input = s; - std::smatch result; - - if (std::regex_match(input, result, re)) { - std::string option = result[1]; - std::string value; - if (result.size() >= 4) { - value = result[3]; - } - for (struct option *op = options; op->name; op++) { - if (strcmp(op->name, option.c_str()) == 0) - return setoption(cfg, op->val, value.c_str()); - } - } -#endif - return 0; -} - #ifndef RNP_RUN_TESTS int main(int argc, char **argv) @@ -633,8 +567,6 @@ int ch; bool disable_ks = false; - rnp_prog_name = argv[0]; - if (argc < 2) { print_usage(usage); return EXIT_ERROR; @@ -654,7 +586,7 @@ optindex = 0; /* TODO: These options should be set after initialising the context. */ - while ((ch = getopt_long(argc, argv, "S:Vdeco:r:su:vz:f:", options, &optindex)) != -1) { + while ((ch = getopt_long(argc, argv, "S:Vdecr:su:vz:f:", options, &optindex)) != -1) { if (ch >= CMD_ENCRYPT) { /* getopt_long returns 0 for long options */ if (!setoption(cfg, options[optindex].val, optarg)) { @@ -681,12 +613,6 @@ case 'v': cmd = CMD_VERIFY; break; - case 'o': - if (!parse_option(cfg, optarg)) { - ERR_MSG("Bad option"); - goto finish; - } - break; case 'r': if (strlen(optarg) < 1) { ERR_MSG("Recipient should not be empty"); @@ -716,6 +642,10 @@ cfg.set_str(CFG_KEYFILE, optarg); cfg.set_bool(CFG_KEYSTORE_DISABLED, true); break; + case '?': + print_usage(usage); + ret = EXIT_FAILURE; + goto finish; default: cmd = CMD_HELP; break; @@ -733,7 +663,7 @@ ret = EXIT_SUCCESS; goto finish; case CMD_VERSION: - print_praise(); + cli_rnp_print_praise(); ret = EXIT_SUCCESS; goto finish; default:; @@ -744,21 +674,19 @@ goto finish; } - if (!cli_rnp_init(&rnp, cfg)) { + if (!rnp.init(cfg)) { ERR_MSG("fatal: cannot initialise"); goto finish; } - disable_ks = cli_rnp_cfg(rnp).get_bool(CFG_KEYSTORE_DISABLED); - if (!disable_ks && - !cli_rnp_load_keyrings(&rnp, cli_rnp_cfg(rnp).get_bool(CFG_NEEDSSECKEY))) { + disable_ks = rnp.cfg().get_bool(CFG_KEYSTORE_DISABLED); + if (!disable_ks && !rnp.load_keyrings(rnp.cfg().get_bool(CFG_NEEDSSECKEY))) { ERR_MSG("fatal: failed to load keys"); goto finish; } /* load the keyfile if any */ - if (disable_ks && !cli_rnp_cfg(rnp).get_str(CFG_KEYFILE).empty() && - !cli_rnp_add_key(&rnp)) { + if (disable_ks && !rnp.cfg().get_str(CFG_KEYFILE).empty() && !cli_rnp_add_key(&rnp)) { ERR_MSG("fatal: failed to load key(s) from the file"); goto finish; } @@ -774,14 +702,14 @@ ret = EXIT_FAILURE; } else { for (int i = optind; i < argc; i++) { - cli_rnp_cfg(rnp).set_str(CFG_INFILE, argv[i]); + rnp.cfg().set_str(CFG_INFILE, argv[i]); if (!rnp_cmd(&rnp)) { ret = EXIT_FAILURE; } } } finish: - cli_rnp_end(&rnp); + rnp.end(); #if !defined(RNP_RUN_TESTS) && defined(_WIN32) if (args_are_substituted) { rnp_win_clear_args(argc, argv); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/CMakeLists.txt thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/CMakeLists.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/CMakeLists.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/CMakeLists.txt 2022-04-15 07:49:22.000000000 +0000 @@ -86,7 +86,7 @@ ) endif() -if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +if (WIN32 AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) target_link_libraries(rnpkeys PRIVATE regex) elseif(MSVC) add_compile_definitions(RNP_USE_STD_REGEX) diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/main.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/main.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/main.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/main.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -41,8 +41,6 @@ extern struct option options[]; extern const char * usage; -const char *rnp_keys_progname = NULL; - #ifndef RNP_RUN_TESTS int main(int argc, char **argv) @@ -59,8 +57,6 @@ int ret = EXIT_FAILURE; int ch; - rnp_keys_progname = argv[0]; - if (argc < 2) { print_usage(usage); return EXIT_FAILURE; @@ -76,7 +72,7 @@ } #endif - while ((ch = getopt_long(argc, argv, "Vglo:", options, &optindex)) != -1) { + while ((ch = getopt_long(argc, argv, "Vgl", options, &optindex)) != -1) { if (ch >= CMD_LIST_KEYS) { /* getopt_long returns 0 for long options */ if (!setoption(cfg, &cmd, options[optindex].val, optarg)) { @@ -86,7 +82,7 @@ } else { switch (ch) { case 'V': - print_praise(); + cli_rnp_print_praise(); ret = EXIT_SUCCESS; goto end; case 'g': @@ -95,12 +91,10 @@ case 'l': cmd = CMD_LIST_KEYS; break; - case 'o': - if (!parse_option(cfg, &cmd, optarg)) { - ERR_MSG("Bad parse_option"); - goto end; - } - break; + case '?': + print_usage(usage); + ret = EXIT_FAILURE; + goto end; default: cmd = CMD_HELP; break; @@ -133,7 +127,7 @@ } end: - cli_rnp_end(&rnp); + rnp.end(); #if !defined(RNP_RUN_TESTS) && defined(_WIN32) if (args_are_substituted) { rnp_win_clear_args(argc, argv); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/rnpkeys.1.adoc thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/rnpkeys.1.adoc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/rnpkeys.1.adoc 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/rnpkeys.1.adoc 2022-04-15 07:49:22.000000000 +0000 @@ -28,6 +28,10 @@ By default, *rnp* will apply a _COMMAND_, additionally configured with _OPTIONS_, to all _INPUT_FILE_(s) or _stdin_ if no _INPUT_FILE_ is given. +There are some special cases for _INPUT_FILE_ : + +* _-_ (dash) substitutes to _stdin_ +* env:VARIABLE_NAME substitutes to the contents of environment variable VARIABLE_NAME Depending on the input, output may be written: @@ -205,7 +209,7 @@ Additional options: *--rev-type*::: -Specifies type of key revocation. +Specifies type of key revocation, see *options* section for the available values. *--rev-reason*::: Specifies reason for key revocation. @@ -224,6 +228,24 @@ *--force*::: Forces removal of a secret key without prompting the user. +*--edit-key* _KEY_:: +Edit or update information, associated with a key. Should be accompanied with editing option. + ++ +Currently the following options are available: + ++ +*--check-cv25519-bits*::: +Check whether least significant/most significant bits of Curve25519 ECDH subkey are correctly set. +RNP internally sets those bits to required values (3 least significant bits and most significant bit must be zero) during decryption, +however other implementations (GnuPG) may require those bits to be set in key material. +_KEY_ must specify the exact subkey via keyid or fingerprint. + +*--fix-cv25519-bits*::: +Set least significant/most significant bits of Curve25519 ECDH subkey to the correct values, and save a key. +So later export of the key would ensure compatibility with other implementations (like GnuPG). +This operation would require the password for your secret key. +Since version 0.16.0 of RNP generated secret key is stored with bits set to a needed value, +however, this may be needed to fix older keys or keys generated by other implementations. +_KEY_ must specify the exact subkey via keyid or fingerprint. === OPTIONS @@ -235,7 +257,11 @@ *--output* _PATH_:: Write data processing related output to the file specified. + + -Combine it with *--force* to overwrite file if it already exists. +Combine it with *--overwrite* to overwrite file if it already exists. + +*--overwrite*:: +Overwrite output file if it already exists. + ++ *--userid* _USERID_:: Use the specified _userid_ during key generation and in some @@ -296,7 +322,7 @@ *--force*:: Force actions to happen without prompting the user. + + -This applies to cases such as output file overwrite, secret key removal, and revoking an already revoked key. +This applies to cases such as secret key removal, revoking an already revoked key and so on. *--permissive*:: Skip malformed or unknown keys/signatures during key import. + @@ -338,6 +364,12 @@ For example, setting it to _2000_ would mean that each secret key decryption operation would take around 2 seconds (on the current machine). +*--notty*:: +Disable use of tty. + ++ +By default RNP would detect whether TTY is attached and use it for user prompts. + ++ +This option overrides default behaviour so user input may be passed in batch mode. == EXIT STATUS @@ -347,6 +379,19 @@ _Non-zero_:: Failure. +== EXAMPLES + +The following examples demonstrate method of usage of the _rnpkeys_ command. + +=== EXAMPLE 1: IMPORT EXISTING KEYS FROM THE GNUPG + +Following oneliner may be used to import all public keys from the GnuPG: + +*gpg* *-a* *--export* | *rnpkeys* *--import* _-_ + +To import all secret keys the following command should be used (please note, that you'll be asked for secret key password(s)): + +*gpg* *-a* *--export-secret-keys* | *rnpkeys* *--import* _-_ == BUGS diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/rnpkeys.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/rnpkeys.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/rnpkeys.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/rnpkeys.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2017-2021, [Ribose Inc](https://www.ribose.com). * Copyright (c) 2009 The NetBSD Foundation, Inc. * All rights reserved. * @@ -39,42 +39,48 @@ #include #include "rnpkeys.h" -// must be placed after include "utils.h" -#ifndef RNP_USE_STD_REGEX -#include -#else -#include -#endif - -extern const char *rnp_keys_progname; - -const char *usage = "-h, --help OR\n" - "\t--export-key [options] OR\n" - "\t--export-rev [options] OR\n" - "\t--revoke-key [options] OR\n" - "\t--generate-key [options] OR\n" - "\t--import, --import-keys, --import-sigs [options] OR\n" - "\t--list-keys [options] OR\n" - "\t--remove-key [options] OR\n" - "\t--version\n" - "where options are:\n" - "\t[--cipher=] AND/OR\n" - "\t[--coredumps] AND/OR\n" - "\t[--expert] AND/OR\n" - "\t[--with-sigs] AND/OR\n" - "\t[--force] AND/OR\n" - "\t[--hash=] AND/OR\n" - "\t[--homedir=] AND/OR\n" - "\t[--keyring=] AND/OR\n" - "\t[--pass-fd=] OR\n" - "\t[--password=] AND/OR\n" - "\t[--permissive] AND/OR\n" - "\t[--output=file] file OR\n" - "\t[--keystore-format=] AND/OR\n" - "\t[--userid=] AND/OR\n" - "\t[--expiration=] AND/OR\n" - "\t[--rev-type, --rev-reason] AND/OR\n" - "\t[--verbose]\n"; +const char *usage = + "Manipulate OpenPGP keys and keyrings.\n" + "Usage: rnpkeys --command [options] [files]\n" + "Commands:\n" + " -h, --help This help message.\n" + " -V, --version Print RNP version information.\n" + " -g, --generate-key Generate a new keypair (default is RSA).\n" + " --userid Specify key's userid.\n" + " --expert Select key type, size, and additional parameters.\n" + " --numbits Override default key size (2048).\n" + " --expiration Set key and subkey expiration time.\n" + " --cipher Set cipher used to encrypt a secret key.\n" + " --hash Set hash which is used for key derivation.\n" + " -l, --list-keys List keys in the keyrings.\n" + " --secret List secret keys instead of public ones.\n" + " --with-sigs List signatures as well.\n" + " --import Import keys or signatures.\n" + " --import-keys Import keys.\n" + " --import-sigs Import signatures.\n" + " --permissive Skip erroring keys/sigs instead of failing.\n" + " --export-key Export a key.\n" + " --secret Export a secret key instead of a public.\n" + " --export-rev Export a key's revocation.\n" + " --rev-type Set revocation type.\n" + " --rev-reason Human-readable reason for revocation.\n" + " --revoke-key Revoke a key specified.\n" + " --remove-key Remove a key specified.\n" + " --edit-key Edit key properties.\n" + " --check-cv25519-bits Check whether Cv25519 subkey bits are correct.\n" + " --fix-cv25519-bits Fix Cv25519 subkey bits.\n" + "\n" + "Other options:\n" + " --homedir Override home directory (default is ~/.rnp/).\n" + " --password Password, which should be used during operation.\n" + " --pass-fd Read password(s) from the file descriptor.\n" + " --force Force operation (like secret key removal).\n" + " --output [file, -] Write data to the specified file or stdout.\n" + " --overwrite Overwrite output file without a prompt.\n" + " --notty Do not write anything to the TTY.\n" + "\n" + "See man page for a detailed listing and explanation.\n" + "\n"; struct option options[] = { /* key-management commands */ @@ -93,6 +99,7 @@ {"export-revocation", no_argument, NULL, CMD_EXPORT_REV}, {"revoke-key", no_argument, NULL, CMD_REVOKE_KEY}, {"remove-key", no_argument, NULL, CMD_REMOVE_KEY}, + {"edit-key", no_argument, NULL, CMD_EDIT_KEY}, /* debugging commands */ {"help", no_argument, NULL, CMD_HELP}, {"version", no_argument, NULL, CMD_VERSION}, @@ -101,29 +108,29 @@ {"coredumps", no_argument, NULL, OPT_COREDUMPS}, {"keystore-format", required_argument, NULL, OPT_KEY_STORE_FORMAT}, {"userid", required_argument, NULL, OPT_USERID}, - {"format", required_argument, NULL, OPT_FORMAT}, {"with-sigs", no_argument, NULL, OPT_WITH_SIGS}, - {"hash-alg", required_argument, NULL, OPT_HASH_ALG}, {"hash", required_argument, NULL, OPT_HASH_ALG}, - {"algorithm", required_argument, NULL, OPT_HASH_ALG}, {"home", required_argument, NULL, OPT_HOMEDIR}, {"homedir", required_argument, NULL, OPT_HOMEDIR}, {"numbits", required_argument, NULL, OPT_NUMBITS}, {"s2k-iterations", required_argument, NULL, OPT_S2K_ITER}, {"s2k-msec", required_argument, NULL, OPT_S2K_MSEC}, {"expiration", required_argument, NULL, OPT_EXPIRATION}, - {"verbose", no_argument, NULL, OPT_VERBOSE}, {"pass-fd", required_argument, NULL, OPT_PASSWDFD}, {"password", required_argument, NULL, OPT_PASSWD}, {"results", required_argument, NULL, OPT_RESULTS}, {"cipher", required_argument, NULL, OPT_CIPHER}, {"expert", no_argument, NULL, OPT_EXPERT}, {"output", required_argument, NULL, OPT_OUTPUT}, + {"overwrite", no_argument, NULL, OPT_OVERWRITE}, {"force", no_argument, NULL, OPT_FORCE}, {"secret", no_argument, NULL, OPT_SECRET}, {"rev-type", required_argument, NULL, OPT_REV_TYPE}, {"rev-reason", required_argument, NULL, OPT_REV_REASON}, {"permissive", no_argument, NULL, OPT_PERMISSIVE}, + {"notty", no_argument, NULL, OPT_NOTTY}, + {"fix-cv25519-bits", no_argument, NULL, OPT_FIX_25519_BITS}, + {"check-cv25519-bits", no_argument, NULL, OPT_CHK_25519_BITS}, {NULL, 0, NULL, 0}, }; @@ -131,8 +138,8 @@ static bool print_keys_info(cli_rnp_t *rnp, FILE *fp, const char *filter) { - bool psecret = cli_rnp_cfg(*rnp).get_bool(CFG_SECRET); - bool psigs = cli_rnp_cfg(*rnp).get_bool(CFG_WITH_SIGS); + bool psecret = rnp->cfg().get_bool(CFG_SECRET); + bool psigs = rnp->cfg().get_bool(CFG_WITH_SIGS); int flags = CLI_SEARCH_SUBKEYS_AFTER | (psecret ? CLI_SEARCH_SECRET : 0); std::vector keys; @@ -164,21 +171,15 @@ } static bool -import_keys(cli_rnp_t *rnp, const char *file) +import_keys(cli_rnp_t *rnp, rnp_input_t input, const std::string &inname) { - rnp_input_t input = NULL; - bool res = false; - bool updated = false; - - if (rnp_input_from_path(&input, file)) { - ERR_MSG("failed to open file %s", file); - return false; - } + bool res = false; + bool updated = false; uint32_t flags = RNP_LOAD_SAVE_PUBLIC_KEYS | RNP_LOAD_SAVE_SECRET_KEYS | RNP_LOAD_SAVE_SINGLE; - bool permissive = cli_rnp_cfg(*rnp).get_bool(CFG_PERMISSIVE); + bool permissive = rnp->cfg().get_bool(CFG_PERMISSIVE); if (permissive) { flags |= RNP_LOAD_SAVE_PERMISSIVE; } @@ -192,7 +193,7 @@ break; } if (ret) { - ERR_MSG("failed to import key(s), from file %s, stopping.", file); + ERR_MSG("failed to import key(s) from %s, stopping.", inname.c_str()); break; } @@ -229,8 +230,8 @@ if (updated) { // set default key if we didn't have one - if (cli_rnp_defkey(rnp).empty()) { - cli_rnp_set_default_key(rnp); + if (rnp->defkey().empty()) { + rnp->set_defkey(); } // save public and secret keyrings @@ -238,21 +239,13 @@ ERR_MSG("failed to save keyrings"); } } - rnp_input_destroy(input); return res; } static bool -import_sigs(cli_rnp_t *rnp, const char *file) +import_sigs(cli_rnp_t *rnp, rnp_input_t input, const std::string &inname) { - rnp_input_t input = NULL; - bool res = false; - - if (rnp_input_from_path(&input, file)) { - ERR_MSG("Failed to open file %s", file); - return false; - } - + bool res = false; char * results = NULL; json_object *jso = NULL; json_object *sigs = NULL; @@ -261,7 +254,7 @@ int old_sigs = 0; if (rnp_import_signatures(rnp->ffi, input, 0, &results)) { - ERR_MSG("Failed to import signatures from file %s", file); + ERR_MSG("Failed to import signatures from %s", inname.c_str()); goto done; } // print information about imported signature(s) @@ -306,56 +299,51 @@ done: json_object_put(jso); rnp_buffer_destroy(results); - rnp_input_destroy(input); return res; } static bool -import(cli_rnp_t *rnp, const char *file, int cmd) +import(cli_rnp_t *rnp, const std::string &spec, int cmd) { - if (!file) { - ERR_MSG("Import file isn't specified"); + if (spec.empty()) { + ERR_MSG("Import path isn't specified"); return false; } - - if (cmd == CMD_IMPORT_KEYS) { - return import_keys(rnp, file); - } - if (cmd == CMD_IMPORT_SIGS) { - return import_sigs(rnp, file); - } - - rnp_input_t input = NULL; - if (rnp_input_from_path(&input, file)) { - ERR_MSG("Failed to open file %s", file); + rnp_input_t input = cli_rnp_input_from_specifier(*rnp, spec, NULL); + if (!input) { + ERR_MSG("Failed to create input for %s", spec.c_str()); return false; } + if (cmd == CMD_IMPORT) { + char *contents = NULL; + if (rnp_guess_contents(input, &contents)) { + ERR_MSG("Warning! Failed to guess content type to import. Assuming keys."); + } + cmd = (contents && !strcmp(contents, "signature")) ? CMD_IMPORT_SIGS : CMD_IMPORT_KEYS; + rnp_buffer_destroy(contents); + } - char *contents = NULL; - if (rnp_guess_contents(input, &contents)) { - ERR_MSG("Warning! Failed to guess content type to import. Assuming keys."); + bool res = false; + switch (cmd) { + case CMD_IMPORT_KEYS: + res = import_keys(rnp, input, spec); + break; + case CMD_IMPORT_SIGS: + res = import_sigs(rnp, input, spec); + break; + default: + ERR_MSG("Unexpected command: %d", cmd); } rnp_input_destroy(input); - bool signature = contents && !strcmp(contents, "signature"); - rnp_buffer_destroy(contents); - - return signature ? import_sigs(rnp, file) : import_keys(rnp, file); -} - -void -print_praise(void) -{ - ERR_MSG("%s\nAll bug reports, praise and chocolate, please, to:\n%s", - PACKAGE_STRING, - PACKAGE_BUGREPORT); + return res; } /* print a usage message */ void print_usage(const char *usagemsg) { - print_praise(); - ERR_MSG("Usage: %s %s", rnp_keys_progname, usagemsg); + cli_rnp_print_praise(); + ERR_MSG("%s", usagemsg); } /* do a command once for a specified file 'f' */ @@ -366,14 +354,14 @@ switch (cmd) { case CMD_LIST_KEYS: - if (!f && cli_rnp_cfg(*rnp).get_count(CFG_USERID)) { - fs = cli_rnp_cfg(*rnp).get_str(CFG_USERID, 0); + if (!f && rnp->cfg().get_count(CFG_USERID)) { + fs = rnp->cfg().get_str(CFG_USERID, 0); f = fs.c_str(); } return print_keys_info(rnp, stdout, f); case CMD_EXPORT_KEY: { - if (!f && cli_rnp_cfg(*rnp).get_count(CFG_USERID)) { - fs = cli_rnp_cfg(*rnp).get_str(CFG_USERID, 0); + if (!f && rnp->cfg().get_count(CFG_USERID)) { + fs = rnp->cfg().get_str(CFG_USERID, 0); f = fs.c_str(); } if (!f) { @@ -385,12 +373,12 @@ case CMD_IMPORT: case CMD_IMPORT_KEYS: case CMD_IMPORT_SIGS: - return import(rnp, f, cmd); + return import(rnp, f ? f : "", cmd); case CMD_GENERATE_KEY: { if (!f) { - size_t count = cli_rnp_cfg(*rnp).get_count(CFG_USERID); + size_t count = rnp->cfg().get_count(CFG_USERID); if (count == 1) { - fs = cli_rnp_cfg(*rnp).get_str(CFG_USERID, 0); + fs = rnp->cfg().get_str(CFG_USERID, 0); f = fs.c_str(); } else if (count > 1) { ERR_MSG("Only single userid is supported for generated keys"); @@ -420,13 +408,20 @@ } return cli_rnp_remove_key(rnp, f); } + case CMD_EDIT_KEY: { + if (!f) { + ERR_MSG("You need to specify a key or subkey to edit."); + return false; + } + return rnp->edit_key(f); + } case CMD_VERSION: - print_praise(); + cli_rnp_print_praise(); return true; case CMD_HELP: default: print_usage(usage); - return false; + return true; } } @@ -436,6 +431,9 @@ { switch (val) { case OPT_COREDUMPS: +#ifdef _WIN32 + ERR_MSG("warning: --coredumps doesn't make sense on windows systems."); +#endif cfg.set_bool(CFG_COREDUMPS, true); return true; case CMD_GENERATE_KEY: @@ -450,6 +448,7 @@ case CMD_EXPORT_REV: case CMD_REVOKE_KEY: case CMD_REMOVE_KEY: + case CMD_EDIT_KEY: case CMD_IMPORT: case CMD_IMPORT_KEYS: case CMD_IMPORT_SIGS: @@ -472,9 +471,6 @@ } cfg.add_str(CFG_USERID, arg); return true; - case OPT_VERBOSE: - cfg.set_int(CFG_VERBOSE, cfg.get_int(CFG_VERBOSE) + 1); - return true; case OPT_HOMEDIR: if (!arg) { ERR_MSG("no home directory argument provided"); @@ -500,12 +496,14 @@ ERR_MSG("No hash algorithm argument provided"); return false; } - bool supported = false; - if (rnp_supports_feature(RNP_FEATURE_HASH_ALG, arg, &supported) || !supported) { + bool supported = false; + const std::string &alg = cli_rnp_alg_to_ffi(arg); + if (rnp_supports_feature(RNP_FEATURE_HASH_ALG, alg.c_str(), &supported) || + !supported) { ERR_MSG("Unsupported hash algorithm: %s", arg); return false; } - cfg.set_str(CFG_HASH, arg); + cfg.set_str(CFG_HASH, alg); return true; } case OPT_S2K_ITER: { @@ -559,24 +557,20 @@ } cfg.set_str(CFG_IO_RESS, arg); return true; - case OPT_FORMAT: - if (!arg) { - ERR_MSG("No key format argument provided"); - return false; - } - cfg.set_str(CFG_KEYFORMAT, arg); - return true; case OPT_CIPHER: { - bool supported = false; - if (rnp_supports_feature(RNP_FEATURE_SYMM_ALG, arg, &supported) || !supported) { + bool supported = false; + const std::string &alg = cli_rnp_alg_to_ffi(arg); + if (rnp_supports_feature(RNP_FEATURE_SYMM_ALG, alg.c_str(), &supported) || + !supported) { ERR_MSG("Unsupported symmetric algorithm: %s", arg); return false; } - cfg.set_str(CFG_CIPHER, arg); + cfg.set_str(CFG_CIPHER, alg); return true; } case OPT_DEBUG: - return !rnp_enable_debug(arg); + ERR_MSG("Option --debug is deprecated, ignoring."); + return true; case OPT_OUTPUT: if (!arg) { ERR_MSG("No output filename argument provided"); @@ -584,6 +578,9 @@ } cfg.set_str(CFG_OUTFILE, arg); return true; + case OPT_OVERWRITE: + cfg.set_bool(CFG_OVERWRITE, true); + return true; case OPT_FORCE: cfg.set_bool(CFG_FORCE, true); return true; @@ -621,73 +618,21 @@ case OPT_PERMISSIVE: cfg.set_bool(CFG_PERMISSIVE, true); return true; + case OPT_NOTTY: + cfg.set_bool(CFG_NOTTY, true); + return true; + case OPT_FIX_25519_BITS: + cfg.set_bool(CFG_FIX_25519_BITS, true); + return true; + case OPT_CHK_25519_BITS: + cfg.set_bool(CFG_CHK_25519_BITS, true); + return true; default: *cmd = CMD_HELP; return true; } } -/* we have -o option=value -- parse, and process */ -bool -parse_option(rnp_cfg &cfg, optdefs_t *cmd, const char *s) -{ -#ifndef RNP_USE_STD_REGEX - static regex_t opt; - struct option *op; - static int compiled; - regmatch_t matches[10]; - char option[128]; - char value[128]; - - if (!compiled) { - compiled = 1; - if (regcomp(&opt, "([^=]{1,128})(=(.*))?", REG_EXTENDED) != 0) { - ERR_MSG("Can't compile regex"); - return false; - } - } - if (regexec(&opt, s, 10, matches, 0) == 0) { - (void) snprintf(option, - sizeof(option), - "%.*s", - (int) (matches[1].rm_eo - matches[1].rm_so), - &s[matches[1].rm_so]); - if (matches[2].rm_so > 0) { - (void) snprintf(value, - sizeof(value), - "%.*s", - (int) (matches[3].rm_eo - matches[3].rm_so), - &s[matches[3].rm_so]); - } else { - value[0] = 0x0; - } - for (op = options; op->name; op++) { - if (strcmp(op->name, option) == 0) { - return setoption(cfg, cmd, op->val, value); - } - } - } -#else - static std::regex re("([^=]{1,128})(=(.*))?", std::regex_constants::extended); - std::string input = s; - std::smatch result; - - if (std::regex_match(input, result, re)) { - std::string option = result[1]; - std::string value; - if (result.size() >= 4) { - value = result[3]; - } - for (struct option *op = options; op->name; op++) { - if (strcmp(op->name, option.c_str()) == 0) { - return setoption(cfg, cmd, op->val, value.c_str()); - } - } - } -#endif - return false; -} - bool rnpkeys_init(cli_rnp_t *rnp, const rnp_cfg &cfg) { @@ -696,23 +641,22 @@ rnpcfg.load_defaults(); rnpcfg.set_int(CFG_NUMBITS, DEFAULT_RSA_NUMBITS); rnpcfg.set_str(CFG_IO_RESS, ""); - rnpcfg.set_str(CFG_KEYFORMAT, "human"); rnpcfg.copy(cfg); if (!cli_cfg_set_keystore_info(rnpcfg)) { ERR_MSG("fatal: cannot set keystore info"); goto end; } - if (!cli_rnp_init(rnp, rnpcfg)) { + if (!rnp->init(rnpcfg)) { ERR_MSG("fatal: failed to initialize rnpkeys"); goto end; } /* TODO: at some point we should check for error here */ - (void) cli_rnp_load_keyrings(rnp, true); + (void) rnp->load_keyrings(true); ret = true; end: if (!ret) { - cli_rnp_end(rnp); + rnp->end(); } return ret; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/rnpkeys.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/rnpkeys.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/rnpkeys.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/rnpkeys.h 2022-04-15 07:49:22.000000000 +0000 @@ -23,6 +23,7 @@ CMD_EXPORT_REV, CMD_REVOKE_KEY, CMD_REMOVE_KEY, + CMD_EDIT_KEY, CMD_VERSION, CMD_HELP, @@ -32,15 +33,14 @@ OPT_HOMEDIR, OPT_NUMBITS, OPT_HASH_ALG, - OPT_VERBOSE, OPT_COREDUMPS, OPT_PASSWDFD, OPT_PASSWD, OPT_RESULTS, OPT_CIPHER, - OPT_FORMAT, OPT_EXPERT, OPT_OUTPUT, + OPT_OVERWRITE, OPT_FORCE, OPT_SECRET, OPT_S2K_ITER, @@ -50,6 +50,9 @@ OPT_REV_TYPE, OPT_REV_REASON, OPT_PERMISSIVE, + OPT_NOTTY, + OPT_FIX_25519_BITS, + OPT_CHK_25519_BITS, /* debug */ OPT_DEBUG @@ -57,9 +60,7 @@ bool rnp_cmd(cli_rnp_t *rnp, optdefs_t cmd, const char *f); bool setoption(rnp_cfg &cfg, optdefs_t *cmd, int val, const char *arg); -void print_praise(void); void print_usage(const char *usagemsg); -bool parse_option(rnp_cfg &cfg, optdefs_t *cmd, const char *s); /** * @brief Initializes rnpkeys. Function allocates memory dynamically for diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/tui.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/tui.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/rnpkeys/tui.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/rnpkeys/tui.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -49,41 +49,31 @@ * -------------------------------------------------------------------------------- */ static bool -rnp_secure_get_long_from_fd(FILE *fp, long *result, bool allow_empty) +rnp_secure_get_long_from_fd(FILE *fp, long &result, bool allow_empty = true) { - char buff[BUFSIZ]; - char *end_ptr; - long num_long; - bool ret = false; - - if (!result) { - goto end; - } - - if (fgets(buff, sizeof(buff), fp) == NULL) { + char buff[BUFSIZ]; + if (!fgets(buff, sizeof(buff), fp)) { RNP_LOG("EOF or read error"); - goto end; - } else { - errno = 0; - num_long = strtol(buff, &end_ptr, 10); - - if (ERANGE == errno) { - RNP_LOG("Number out of range"); - goto end; - } else if (end_ptr == buff) { - ret = allow_empty; - goto end; - } else if ('\n' != *end_ptr && '\0' != *end_ptr) { - RNP_LOG("Unexpected end of line"); - goto end; - } + return false; } - *result = num_long; - ret = true; + errno = 0; + char *end_ptr = NULL; + long num_long = strtol(buff, &end_ptr, 10); + if (ERANGE == errno) { + RNP_LOG("Number out of range"); + return false; + } + if (end_ptr == buff) { + return allow_empty; + } + if ('\n' != *end_ptr && '\0' != *end_ptr) { + RNP_LOG("Unexpected end of line"); + return false; + } -end: - return ret; + result = num_long; + return true; } static bool @@ -95,9 +85,6 @@ static const char * ask_curve_name(FILE *input_fp) { - const char * result = NULL; - long val = 0; - bool ok = false; std::vector curves; static const char *const known_curves[] = { "NIST P-256", @@ -124,17 +111,28 @@ return NULL; } const size_t ccount = curves.size(); + if (!ccount) { + return NULL; + } + bool ok = false; + const char *result = NULL; + int attempts = 0; do { + if (attempts >= 10) { + printf("Too many attempts. Aborting.\n"); + return NULL; + } printf("Please select which elliptic curve you want:\n"); for (size_t i = 0; i < ccount; i++) { printf("\t(%zu) %s\n", i + 1, curves[i]); } printf("(default %s)> ", DEFAULT_CURVE); - ok = rnp_secure_get_long_from_fd(input_fp, &val, true) && (val > 0) && - (val <= (long) ccount); + long val = 0; + ok = rnp_secure_get_long_from_fd(input_fp, val) && (val > 0) && (val <= (long) ccount); if (ok) { result = curves[val - 1]; } + attempts++; } while (!ok); return result; @@ -148,7 +146,7 @@ result = DEFAULT_RSA_NUMBITS; printf("Please provide bit length of the key (between 1024 and 4096):\n(default %d)> ", DEFAULT_RSA_NUMBITS); - } while (!rnp_secure_get_long_from_fd(input_fp, &result, true) || + } while (!rnp_secure_get_long_from_fd(input_fp, result) || !is_rsa_keysize_supported(result)); return result; } @@ -156,24 +154,26 @@ static long ask_dsa_bitlen(FILE *input_fp) { - long result = 0; do { - result = DSA_DEFAULT_P_BITLEN; printf( "Please provide bit length of the DSA key (between %d and %d):\n(default %d) > ", DSA_MIN_P_BITLEN, DSA_MAX_P_BITLEN, DSA_DEFAULT_P_BITLEN); - } while (!rnp_secure_get_long_from_fd(input_fp, &result, true) || - (result < DSA_MIN_P_BITLEN) || (result > DSA_MAX_P_BITLEN)); - - // round up to multiple of 1024 - result = ((result + 63) / 64) * 64; - printf("Bitlen of the key will be %lu\n", result); - return result; + long result = DSA_DEFAULT_P_BITLEN; + if (!rnp_secure_get_long_from_fd(input_fp, result)) { + continue; + } + if ((result >= DSA_MIN_P_BITLEN) && (result <= DSA_MAX_P_BITLEN)) { + // round up to multiple of 64 + result = ((result + 63) / 64) * 64; + printf("Bitlen of the key will be %lu\n", result); + return result; + } + } while (1); } -static void +static bool rnpkeys_ask_generate_params(rnp_cfg &cfg, FILE *input_fp) { long option = 0; @@ -186,7 +186,7 @@ "\t(22) EDDSA + X25519\n" "\t(99) SM2\n" "> "); - if (!rnp_secure_get_long_from_fd(input_fp, &option, false)) { + if (!rnp_secure_get_long_from_fd(input_fp, option, false)) { option = 0; continue; } @@ -217,6 +217,9 @@ } case 19: { const char *curve = ask_curve_name(input_fp); + if (!curve) { + return false; + } cfg.set_str(CFG_KG_PRIMARY_ALG, RNP_ALGNAME_ECDSA); cfg.set_str(CFG_KG_SUBKEY_ALG, RNP_ALGNAME_ECDH); cfg.set_str(CFG_KG_PRIMARY_CURVE, curve); @@ -242,6 +245,8 @@ break; } } while (!option); + + return true; } bool @@ -271,11 +276,16 @@ } } } - res = res && input; - rnpkeys_ask_generate_params(cfg, input); - if (input && (input != stdin)) { + if (!input) { + return false; + } + res = rnpkeys_ask_generate_params(cfg, input); + if (input != stdin) { fclose(input); } + if (!res) { + return false; + } } // make sure hash algorithms are set diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cipher.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cipher.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cipher.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cipher.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -35,12 +35,9 @@ #include "support.h" #include "fingerprint.h" -extern rng_t global_rng; - TEST_F(rnp_tests, hash_test_success) { - pgp_hash_t hash = {0}; - uint8_t hash_output[PGP_MAX_HASH_SIZE]; + uint8_t hash_output[PGP_MAX_HASH_SIZE]; const pgp_hash_alg_t hash_algs[] = {PGP_HASH_MD5, PGP_HASH_SHA1, @@ -71,19 +68,27 @@ "0E116E9192AF3C91A7EC57647E3934057340B4CF408D5A56592F8274EEC53F0"}; for (int i = 0; hash_algs[i] != PGP_HASH_UNKNOWN; ++i) { - assert_int_equal(1, pgp_hash_create(&hash, hash_algs[i])); - size_t hash_size = pgp_digest_length(hash_algs[i]); - +#if !defined(ENABLE_SM2) + if (hash_algs[i] == PGP_HASH_SM3) { + assert_throw({ rnp::Hash hash(hash_algs[i]); }); + size_t hash_size = rnp::Hash::size(hash_algs[i]); + assert_int_equal(hash_size * 2, strlen(hash_alg_expected_outputs[i])); + continue; + } +#endif + rnp::Hash hash(hash_algs[i]); + size_t hash_size = rnp::Hash::size(hash_algs[i]); assert_int_equal(hash_size * 2, strlen(hash_alg_expected_outputs[i])); - pgp_hash_add(&hash, test_input, 1); - pgp_hash_add(&hash, test_input + 1, sizeof(test_input) - 1); - pgp_hash_finish(&hash, hash_output); - - assert_int_equal( - 0, - test_value_equal( - pgp_hash_name(&hash), hash_alg_expected_outputs[i], hash_output, hash_size)); + hash.add(test_input, 1); + hash.add(test_input + 1, sizeof(test_input) - 1); + hash.finish(hash_output); + + assert_int_equal(0, + test_value_equal(rnp::Hash::name(hash_algs[i]), + hash_alg_expected_outputs[i], + hash_output, + hash_size)); } } @@ -124,42 +129,42 @@ uint8_t dec[1024 / 8]; pgp_rsa_encrypted_t enc; size_t dec_size; - pgp_key_pkt_t seckey; - - const pgp_rsa_key_t *key_rsa; rnp_keygen_crypto_params_t key_desc; key_desc.key_alg = PGP_PKA_RSA; key_desc.hash_alg = PGP_HASH_SHA256; key_desc.rsa.modulus_bit_len = 1024; - key_desc.rng = &global_rng; - assert_true(pgp_generate_seckey(&key_desc, &seckey, true)); - key_rsa = &seckey.material.rsa; + key_desc.ctx = &global_ctx; + pgp_key_pkt_t seckey; + assert_true(pgp_generate_seckey(key_desc, seckey, true)); + const pgp_rsa_key_t *key_rsa = &seckey.material.rsa; - assert_rnp_success(rsa_encrypt_pkcs1(&global_rng, &enc, ptext, 3, key_rsa)); + assert_rnp_success(rsa_encrypt_pkcs1(&global_ctx.rng, &enc, ptext, 3, key_rsa)); assert_int_equal(enc.m.len, 1024 / 8); memset(dec, 0, sizeof(dec)); dec_size = 0; - assert_rnp_success(rsa_decrypt_pkcs1(&global_rng, dec, &dec_size, &enc, key_rsa)); + assert_rnp_success(rsa_decrypt_pkcs1(&global_ctx.rng, dec, &dec_size, &enc, key_rsa)); test_value_equal("RSA 1024 decrypt", "616263", dec, 3); assert_int_equal(dec_size, 3); } TEST_F(rnp_tests, rnp_test_eddsa) { + rnp::SecurityContext ctx; rnp_keygen_crypto_params_t key_desc; key_desc.key_alg = PGP_PKA_EDDSA; key_desc.hash_alg = PGP_HASH_SHA256; - key_desc.rng = &global_rng; + key_desc.ctx = &ctx; pgp_key_pkt_t seckey; - assert_true(pgp_generate_seckey(&key_desc, &seckey, true)); + assert_true(pgp_generate_seckey(key_desc, seckey, true)); const uint8_t hash[32] = {0}; pgp_ec_signature_t sig = {{{0}}}; - assert_rnp_success(eddsa_sign(&global_rng, &sig, hash, sizeof(hash), &seckey.material.ec)); + assert_rnp_success( + eddsa_sign(&global_ctx.rng, &sig, hash, sizeof(hash), &seckey.material.ec)); assert_rnp_success(eddsa_verify(&sig, hash, sizeof(hash), &seckey.material.ec)); @@ -185,13 +190,18 @@ key_desc.key_alg = PGP_PKA_ECDH; key_desc.hash_alg = PGP_HASH_SHA256; - key_desc.rng = &global_rng; + key_desc.ctx = &global_ctx; key_desc.ecc.curve = PGP_CURVE_25519; - assert_true(pgp_generate_seckey(&key_desc, &seckey, true)); + assert_true(pgp_generate_seckey(key_desc, seckey, true)); + /* check for length and correctly tweaked bits */ + assert_int_equal(seckey.material.ec.x.len, 32); + assert_int_equal(seckey.material.ec.x.mpi[31] & 7, 0); + assert_int_equal(seckey.material.ec.x.mpi[0] & 128, 0); + assert_int_equal(seckey.material.ec.x.mpi[0] & 64, 64); assert_rnp_success(pgp_fingerprint(fp, seckey)); assert_rnp_success( - ecdh_encrypt_pkcs5(&global_rng, &enc, in, sizeof(in), &seckey.material.ec, fp)); + ecdh_encrypt_pkcs5(&global_ctx.rng, &enc, in, sizeof(in), &seckey.material.ec, fp)); assert_true(enc.mlen > 16); assert_true((enc.p.mpi[0] == 0x40) && (enc.p.len == 33)); outlen = sizeof(out); @@ -223,9 +233,9 @@ uint8_t res[1024]; size_t res_len = 0; - assert_int_equal(elgamal_encrypt_pkcs1(&global_rng, &enc, in_b, sizeof(in_b), key), + assert_int_equal(elgamal_encrypt_pkcs1(&global_ctx.rng, &enc, in_b, sizeof(in_b), key), RNP_SUCCESS); - assert_int_equal(elgamal_decrypt_pkcs1(&global_rng, res, &res_len, &enc, key), + assert_int_equal(elgamal_decrypt_pkcs1(&global_ctx.rng, res, &res_len, &enc, key), RNP_SUCCESS); assert_int_equal(res_len, sizeof(in_b)); assert_int_equal(0, test_value_equal("ElGamal decrypt", "0102030417", res, res_len)); @@ -235,7 +245,7 @@ { pgp_eg_key_t key; - assert_int_equal(elgamal_generate(&global_rng, &key, 1024), RNP_SUCCESS); + assert_int_equal(elgamal_generate(&global_ctx.rng, &key, 1024), RNP_SUCCESS); elgamal_roundtrip(&key); } @@ -252,26 +262,26 @@ for (size_t i = 0; i < ARRAY_SIZE(curves); i++) { // Generate test data. Mainly to make valgrind not to complain about uninitialized data - assert_true(rng_get_data(&global_rng, message, sizeof(message))); + global_ctx.rng.get(message, sizeof(message)); pgp_ec_signature_t sig = {{{0}}}; rnp_keygen_crypto_params_t key_desc; key_desc.key_alg = PGP_PKA_ECDSA; key_desc.hash_alg = hash_alg; key_desc.ecc.curve = curves[i].id; - key_desc.rng = &global_rng; + key_desc.ctx = &global_ctx; pgp_key_pkt_t seckey1; pgp_key_pkt_t seckey2; - assert_true(pgp_generate_seckey(&key_desc, &seckey1, true)); - assert_true(pgp_generate_seckey(&key_desc, &seckey2, true)); + assert_true(pgp_generate_seckey(key_desc, seckey1, true)); + assert_true(pgp_generate_seckey(key_desc, seckey2, true)); const pgp_ec_key_t *key1 = &seckey1.material.ec; const pgp_ec_key_t *key2 = &seckey2.material.ec; assert_rnp_success( - ecdsa_sign(&global_rng, &sig, hash_alg, message, sizeof(message), key1)); + ecdsa_sign(&global_ctx.rng, &sig, hash_alg, message, sizeof(message), key1)); assert_rnp_success(ecdsa_verify(&sig, hash_alg, message, sizeof(message), key1)); @@ -303,16 +313,20 @@ key_desc.key_alg = PGP_PKA_ECDH; key_desc.hash_alg = PGP_HASH_SHA512; key_desc.ecc.curve = curves[i].id; - key_desc.rng = &global_rng; + key_desc.ctx = &global_ctx; pgp_key_pkt_t ecdh_key1; - assert_true(pgp_generate_seckey(&key_desc, &ecdh_key1, true)); + assert_true(pgp_generate_seckey(key_desc, ecdh_key1, true)); pgp_fingerprint_t ecdh_key1_fpr = {}; assert_rnp_success(pgp_fingerprint(ecdh_key1_fpr, ecdh_key1)); - assert_rnp_success(ecdh_encrypt_pkcs5( - &global_rng, &enc, plaintext, plaintext_len, &ecdh_key1.material.ec, ecdh_key1_fpr)); + assert_rnp_success(ecdh_encrypt_pkcs5(&global_ctx.rng, + &enc, + plaintext, + plaintext_len, + &ecdh_key1.material.ec, + ecdh_key1_fpr)); assert_rnp_success(ecdh_decrypt_pkcs5( result, &result_len, &enc, &ecdh_key1.material.ec, ecdh_key1_fpr)); @@ -334,16 +348,16 @@ key_desc.key_alg = PGP_PKA_ECDH; key_desc.hash_alg = PGP_HASH_SHA512; key_desc.ecc = {.curve = PGP_CURVE_NIST_P_256}; - key_desc.rng = &global_rng; + key_desc.ctx = &global_ctx; pgp_key_pkt_t ecdh_key1; - assert_true(pgp_generate_seckey(&key_desc, &ecdh_key1, true)); + assert_true(pgp_generate_seckey(key_desc, ecdh_key1, true)); pgp_fingerprint_t ecdh_key1_fpr = {}; assert_rnp_success(pgp_fingerprint(ecdh_key1_fpr, ecdh_key1)); assert_rnp_success(ecdh_encrypt_pkcs5( - &global_rng, &enc, plaintext, plaintext_len, &ecdh_key1.material.ec, ecdh_key1_fpr)); + &global_ctx.rng, &enc, plaintext, plaintext_len, &ecdh_key1.material.ec, ecdh_key1_fpr)); assert_int_equal(ecdh_decrypt_pkcs5(NULL, 0, &enc, &ecdh_key1.material.ec, ecdh_key1_fpr), RNP_ERROR_BAD_PARAMETERS); @@ -374,6 +388,7 @@ ecdh_key1.material.ec.key_wrap_alg = (pgp_symm_alg_t) key_wrapping_alg; } +#if defined(ENABLE_SM2) TEST_F(rnp_tests, sm2_roundtrip) { uint8_t key[27] = {0}; @@ -384,12 +399,12 @@ key_desc.key_alg = PGP_PKA_SM2; key_desc.hash_alg = PGP_HASH_SM3; key_desc.ecc = {.curve = PGP_CURVE_SM2_P_256}; - key_desc.rng = &global_rng; + key_desc.ctx = &global_ctx; - assert_true(rng_get_data(&global_rng, key, sizeof(key))); + global_ctx.rng.get(key, sizeof(key)); pgp_key_pkt_t seckey; - assert_true(pgp_generate_seckey(&key_desc, &seckey, true)); + assert_true(pgp_generate_seckey(key_desc, seckey, true)); const pgp_ec_key_t *eckey = &seckey.material.ec; @@ -398,7 +413,7 @@ rnp_result_t ret; for (size_t i = 0; i < ARRAY_SIZE(hashes); ++i) { - ret = sm2_encrypt(&global_rng, &enc, key, sizeof(key), hashes[i], eckey); + ret = sm2_encrypt(&global_ctx.rng, &enc, key, sizeof(key), hashes[i], eckey); assert_int_equal(ret, RNP_SUCCESS); memset(decrypted, 0, sizeof(decrypted)); @@ -411,23 +426,21 @@ } } } +#endif +#if defined(ENABLE_SM2) TEST_F(rnp_tests, sm2_sm3_signature_test) { const char *msg = "no backdoors here"; pgp_ec_key_t sm2_key; - pgp_hash_t hash; - rng_t rng; pgp_ec_signature_t sig; pgp_hash_alg_t hash_alg = PGP_HASH_SM3; - const size_t hash_len = pgp_digest_length(hash_alg); + const size_t hash_len = rnp::Hash::size(hash_alg); uint8_t digest[PGP_MAX_HASH_SIZE]; - rng_init(&rng, RNG_SYSTEM); - sm2_key.curve = PGP_CURVE_NIST_P_256; hex2mpi(&sm2_key.p, @@ -435,91 +448,74 @@ "c82f49ee0a5b11df22cb0c3c6d9d5526d9e24d02ff8c83c06a859c26565f1"); hex2mpi(&sm2_key.x, "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC"); - assert_int_equal(sm2_validate_key(&rng, &sm2_key, true), RNP_SUCCESS); + assert_int_equal(sm2_validate_key(&global_ctx.rng, &sm2_key, true), RNP_SUCCESS); - pgp_hash_create(&hash, hash_alg); - - assert_int_equal(sm2_compute_za(&sm2_key, &hash, "sm2_p256_test@example.com"), - RNP_SUCCESS); + rnp::Hash hash(hash_alg); - pgp_hash_add(&hash, msg, strlen(msg)); - - pgp_hash_finish(&hash, digest); + assert_int_equal(sm2_compute_za(sm2_key, hash, "sm2_p256_test@example.com"), RNP_SUCCESS); + hash.add(msg, strlen(msg)); + assert_int_equal(hash.finish(digest), hash_len); // First generate a signature, then verify it - assert_int_equal(sm2_sign(&rng, &sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); - + assert_int_equal(sm2_sign(&global_ctx.rng, &sig, hash_alg, digest, hash_len, &sm2_key), + RNP_SUCCESS); assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); // Check that invalid signatures are rejected digest[0] ^= 1; - assert_int_not_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); digest[0] ^= 1; - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); // Now verify a known good signature for this key/message (generated by GmSSL) hex2mpi(&sig.r, "96AA39A0C4A5C454653F394E86386F2E38BE14C57D0E555F3A27A5CEF30E51BD"); hex2mpi(&sig.s, "62372BE4AC97DBE725AC0B279BB8FD15883858D814FD792DDB0A401DCC988E70"); assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); - rng_destroy(&rng); } +#endif +#if defined(ENABLE_SM2) TEST_F(rnp_tests, sm2_sha256_signature_test) { - const char *msg = "hi chappy"; - + const char * msg = "hi chappy"; pgp_ec_key_t sm2_key; - pgp_hash_t hash; - rng_t rng; pgp_ec_signature_t sig; - - pgp_hash_alg_t hash_alg = PGP_HASH_SHA256; - const size_t hash_len = pgp_digest_length(hash_alg); - - uint8_t digest[PGP_MAX_HASH_SIZE]; - - rng_init(&rng, RNG_SYSTEM); + pgp_hash_alg_t hash_alg = PGP_HASH_SHA256; + const size_t hash_len = rnp::Hash::size(hash_alg); + uint8_t digest[PGP_MAX_HASH_SIZE]; sm2_key.curve = PGP_CURVE_SM2_P_256; - hex2mpi(&sm2_key.p, "04d03d30dd01ca3422aeaccf9b88043b554659d3092b0a9e8cce3e8c4530a98cb79d7" "05e6213eee145b748e36e274e5f101dc10d7bbc9dab9a04022e73b76e02cd"); hex2mpi(&sm2_key.x, "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC"); - assert_int_equal(sm2_validate_key(&rng, &sm2_key, true), RNP_SUCCESS); - - pgp_hash_create(&hash, hash_alg); - - assert_int_equal(sm2_compute_za(&sm2_key, &hash, "sm2test@example.com"), RNP_SUCCESS); - - pgp_hash_add(&hash, msg, strlen(msg)); + assert_int_equal(sm2_validate_key(&global_ctx.rng, &sm2_key, true), RNP_SUCCESS); - pgp_hash_finish(&hash, digest); + rnp::Hash hash(hash_alg); + assert_int_equal(sm2_compute_za(sm2_key, hash, "sm2test@example.com"), RNP_SUCCESS); + hash.add(msg, strlen(msg)); + assert_int_equal(hash.finish(digest), hash_len); // First generate a signature, then verify it - assert_int_equal(sm2_sign(&rng, &sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); - + assert_int_equal(sm2_sign(&global_ctx.rng, &sig, hash_alg, digest, hash_len, &sm2_key), + RNP_SUCCESS); assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); // Check that invalid signatures are rejected digest[0] ^= 1; - assert_int_not_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); digest[0] ^= 1; - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); // Now verify a known good signature for this key/message (generated by GmSSL) hex2mpi(&sig.r, "94DA20EA69E4FC70692158BF3D30F87682A4B2F84DF4A4829A1EFC5D9C979D3F"); hex2mpi(&sig.s, "EE15AF8D455B728AB80E592FCB654BF5B05620B2F4D25749D263D5C01FAD365F"); assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); - rng_destroy(&rng); } +#endif TEST_F(rnp_tests, test_dsa_roundtrip) { @@ -547,7 +543,7 @@ {1024, 256, PGP_HASH_SHA256}, }; - assert_true(rng_get_data(&global_rng, message, sizeof(message))); + global_ctx.rng.get(message, sizeof(message)); for (size_t i = 0; i < ARRAY_SIZE(keys); i++) { sig = {}; @@ -556,20 +552,20 @@ key_desc.hash_alg = keys[i].h; key_desc.dsa.p_bitlen = keys[i].p; key_desc.dsa.q_bitlen = keys[i].q; - key_desc.rng = &global_rng; + key_desc.ctx = &global_ctx; - assert_true(pgp_generate_seckey(&key_desc, &seckey, true)); + assert_true(pgp_generate_seckey(key_desc, seckey, true)); // try to prevent timeouts in travis-ci printf("p: %zu q: %zu h: %s\n", key_desc.dsa.p_bitlen, key_desc.dsa.q_bitlen, - pgp_show_hash_alg(key_desc.hash_alg)); + rnp::Hash::name(key_desc.hash_alg)); fflush(stdout); pgp_dsa_key_t *key1 = &seckey.material.dsa; - size_t h_size = pgp_digest_length(keys[i].h); - assert_int_equal(dsa_sign(&global_rng, &sig, message, h_size, key1), RNP_SUCCESS); + size_t h_size = rnp::Hash::size(keys[i].h); + assert_int_equal(dsa_sign(&global_ctx.rng, &sig, message, h_size, key1), RNP_SUCCESS); assert_int_equal(dsa_verify(&sig, message, h_size, key1), RNP_SUCCESS); } } @@ -587,28 +583,28 @@ pgp_hash_alg_t h; } key = {1024, 160, PGP_HASH_SHA1}; - assert_true(rng_get_data(&global_rng, message, sizeof(message))); + global_ctx.rng.get(message, sizeof(message)); rnp_keygen_crypto_params_t key_desc; key_desc.key_alg = PGP_PKA_DSA; key_desc.hash_alg = key.h; key_desc.dsa.p_bitlen = key.p; key_desc.dsa.q_bitlen = key.q; - key_desc.rng = &global_rng; + key_desc.ctx = &global_ctx; - assert_true(pgp_generate_seckey(&key_desc, &sec_key1, true)); + assert_true(pgp_generate_seckey(key_desc, sec_key1, true)); // try to prevent timeouts in travis-ci printf("p: %zu q: %zu h: %s\n", key_desc.dsa.p_bitlen, key_desc.dsa.q_bitlen, - pgp_show_hash_alg(key_desc.hash_alg)); - assert_true(pgp_generate_seckey(&key_desc, &sec_key2, true)); + rnp::Hash::name(key_desc.hash_alg)); + assert_true(pgp_generate_seckey(key_desc, sec_key2, true)); pgp_dsa_key_t *key1 = &sec_key1.material.dsa; pgp_dsa_key_t *key2 = &sec_key2.material.dsa; - size_t h_size = pgp_digest_length(key.h); - assert_int_equal(dsa_sign(&global_rng, &sig, message, h_size, key1), RNP_SUCCESS); + size_t h_size = rnp::Hash::size(key.h); + assert_int_equal(dsa_sign(&global_ctx.rng, &sig, message, h_size, key1), RNP_SUCCESS); // wrong key used assert_int_equal(dsa_verify(&sig, message, h_size, key2), RNP_ERROR_SIGNATURE_INVALID); // different message @@ -616,6 +612,12 @@ assert_int_equal(dsa_verify(&sig, message, h_size, key1), RNP_ERROR_SIGNATURE_INVALID); } +// platforms known to not have a robust response can compile with +// -DS2K_MINIMUM_TUNING_RATIO=2 (or whatever they need) +#ifndef S2K_MINIMUM_TUNING_RATIO +#define S2K_MINIMUM_TUNING_RATIO 6 +#endif + TEST_F(rnp_tests, s2k_iteration_tuning) { pgp_hash_alg_t hash_alg = PGP_HASH_SHA512; @@ -629,9 +631,10 @@ const size_t iters_100 = pgp_s2k_compute_iters(hash_alg, 100, TRIAL_MSEC); const size_t iters_10 = pgp_s2k_compute_iters(hash_alg, 10, TRIAL_MSEC); - // fprintf(stderr, "%d %d\n", iters_10, iters_100); + double ratio = static_cast(iters_100) / iters_10; + printf("s2k iteration tuning ratio: %g, (%zu:%zu)\n", ratio, iters_10, iters_100); // Test roughly linear cost, often skeyed by clock idle - assert_greater_than(static_cast(iters_100) / iters_10, 6); + assert_greater_than(ratio, S2K_MINIMUM_TUNING_RATIO); // Should not crash for unknown hash algorithm assert_int_equal(pgp_s2k_compute_iters(PGP_HASH_UNKNOWN, 1000, TRIAL_MSEC), 0); @@ -678,8 +681,7 @@ TEST_F(rnp_tests, test_validate_key_material) { pgp_key_pkt_t key; - rng_t rng = {}; - rng_init(&rng, RNG_SYSTEM); + rnp::RNG & rng = global_ctx.rng; /* RSA key and subkey */ assert_true(read_key_pkt(&key, KEYS "rsa-pub.pgp")); @@ -701,7 +703,13 @@ key = pgp_key_pkt_t(); assert_true(read_key_pkt(&key, KEYS "rsa-sec.pgp")); + key.material.validate(global_ctx); + assert_true(key.material.validity.valid); + assert_true(key.material.validity.validated); assert_rnp_success(decrypt_secret_key(&key, NULL)); + /* make sure validity is reset after decryption */ + assert_false(key.material.validity.valid); + assert_false(key.material.validity.validated); assert_true(key.material.secret); assert_rnp_success(validate_pgp_key_material(&key.material, &rng)); key.material.rsa.e.mpi[key.material.rsa.e.len - 1] += 1; @@ -766,6 +774,17 @@ assert_rnp_failure(validate_pgp_key_material(&key.material, &rng)); key = pgp_key_pkt_t(); + /* ElGamal key with small subgroup */ + assert_true(read_key_pkt(&key, KEYS "eg-sec-small-group.pgp")); + assert_rnp_failure(validate_pgp_key_material(&key.material, &rng)); + assert_rnp_success(decrypt_secret_key(&key, NULL)); + key = pgp_key_pkt_t(); + + assert_true(read_key_pkt(&key, KEYS "eg-sec-small-group-enc.pgp")); + assert_rnp_failure(validate_pgp_key_material(&key.material, &rng)); + assert_rnp_success(decrypt_secret_key(&key, "password")); + key = pgp_key_pkt_t(); + /* ECDSA key */ assert_true(read_key_pkt(&key, KEYS "ecdsa-p256-sec.pgp")); assert_rnp_success(validate_pgp_key_material(&key.material, &rng)); @@ -807,6 +826,167 @@ assert_rnp_failure(validate_pgp_key_material(&key.material, &rng)); key.material.ec.p.mpi[0] -= 2; key = pgp_key_pkt_t(); +} - rng_destroy(&rng); +TEST_F(rnp_tests, test_sm2_enabled) +{ + char *features = NULL; + bool supported = false; + /* check whether FFI returns value which corresponds to defines */ +#if defined(ENABLE_SM2) + assert_true(sm2_enabled()); + /* SM2 */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_PK_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM2") != std::string::npos); + rnp_buffer_destroy(features); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "SM2", &supported)); + assert_true(supported); + /* SM3 */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_HASH_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM3") != std::string::npos); + rnp_buffer_destroy(features); + supported = false; + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "SM3", &supported)); + assert_true(supported); + /* SM4 */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_SYMM_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM4") != std::string::npos); + rnp_buffer_destroy(features); + supported = false; + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "SM4", &supported)); + assert_true(supported); + /* Curve */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_CURVE, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM2 P-256") != std::string::npos); + rnp_buffer_destroy(features); + supported = false; + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "SM2 P-256", &supported)); + assert_true(supported); +#else + assert_false(sm2_enabled()); + /* SM2 */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_PK_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM2") == std::string::npos); + rnp_buffer_destroy(features); + supported = true; + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "SM2", &supported)); + assert_false(supported); + /* SM3 */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_HASH_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM3") == std::string::npos); + rnp_buffer_destroy(features); + supported = true; + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "SM3", &supported)); + assert_false(supported); + /* SM4 */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_SYMM_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM4") == std::string::npos); + rnp_buffer_destroy(features); + supported = true; + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "SM4", &supported)); + assert_false(supported); + /* Curve */ + assert_rnp_success(rnp_supported_features(RNP_FEATURE_CURVE, &features)); + assert_non_null(features); + assert_true(std::string(features).find("SM2 P-256") == std::string::npos); + rnp_buffer_destroy(features); + supported = true; + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "SM2 P-256", &supported)); + assert_false(supported); +#endif +} + +TEST_F(rnp_tests, test_aead_enabled) +{ + char *features = NULL; + bool supported = false; + /* check whether FFI returns value which corresponds to defines */ +#if defined(ENABLE_AEAD) + assert_true(aead_eax_enabled()); + assert_true(aead_ocb_enabled()); + assert_rnp_success(rnp_supported_features(RNP_FEATURE_AEAD_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("EAX") != std::string::npos); + assert_true(std::string(features).find("OCB") != std::string::npos); + rnp_buffer_destroy(features); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "EAX", &supported)); + assert_true(supported); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "OCB", &supported)); + assert_true(supported); +#else + assert_false(aead_eax_enabled()); + assert_false(aead_ocb_enabled()); + assert_rnp_success(rnp_supported_features(RNP_FEATURE_AEAD_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("EAX") == std::string::npos); + assert_true(std::string(features).find("OCB") == std::string::npos); + rnp_buffer_destroy(features); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "EAX", &supported)); + assert_false(supported); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "OCB", &supported)); + assert_false(supported); +#endif +} + +TEST_F(rnp_tests, test_twofish_enabled) +{ + char *features = NULL; + bool supported = false; + /* check whether FFI returns value which corresponds to defines */ +#if defined(ENABLE_TWOFISH) + assert_true(twofish_enabled()); + assert_rnp_success(rnp_supported_features(RNP_FEATURE_SYMM_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("TWOFISH") != std::string::npos); + rnp_buffer_destroy(features); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "TWOFISH", &supported)); + assert_true(supported); +#else + assert_false(twofish_enabled()); + assert_rnp_success(rnp_supported_features(RNP_FEATURE_SYMM_ALG, &features)); + assert_non_null(features); + assert_true(std::string(features).find("TWOFISH") == std::string::npos); + rnp_buffer_destroy(features); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "TWOFISH", &supported)); + assert_false(supported); +#endif +} + +TEST_F(rnp_tests, test_brainpool_enabled) +{ + char *features = NULL; + bool supported = false; + /* check whether FFI returns value which corresponds to defines */ +#if defined(ENABLE_BRAINPOOL) + assert_true(brainpool_enabled()); + assert_rnp_success(rnp_supported_features(RNP_FEATURE_CURVE, &features)); + assert_non_null(features); + assert_true(std::string(features).find("brainpool") != std::string::npos); + rnp_buffer_destroy(features); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP256r1", &supported)); + assert_true(supported); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP384r1", &supported)); + assert_true(supported); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP512r1", &supported)); + assert_true(supported); +#else + assert_false(brainpool_enabled()); + assert_rnp_success(rnp_supported_features(RNP_FEATURE_CURVE, &features)); + assert_non_null(features); + assert_true(std::string(features).find("brainpool") == std::string::npos); + rnp_buffer_destroy(features); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP256r1", &supported)); + assert_false(supported); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP384r1", &supported)); + assert_false(supported); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP512r1", &supported)); + assert_false(supported); +#endif } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cipher_cxx.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cipher_cxx.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cipher_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cipher_cxx.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017-2021 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include "rnp_tests.h" +#include "support.h" +#include "utils.h" +#include +#include +#include +#include + +static std::vector +decode_hex(const char *hex) +{ + if (!hex) { + return {}; + } + std::vector data(strlen(hex) / 2); + assert_true(rnp::hex_decode(hex, data.data(), data.size())); + return data; +} + +void +test_cipher(pgp_symm_alg_t alg, + pgp_cipher_mode_t mode, + size_t tag_size, + bool disable_padding, + const char * key_hex, + const char * iv_hex, + const char * ad_hex, + const char * pt_hex, + const char * expected_ct_hex) +{ + const std::vector key(decode_hex(key_hex)); + const std::vector iv(decode_hex(iv_hex)); + const std::vector ad(decode_hex(ad_hex)); + const std::vector pt(decode_hex(pt_hex)); + const std::vector expected_ct(decode_hex(expected_ct_hex)); + + auto enc = Cipher::encryption(alg, mode, tag_size, disable_padding); + const size_t block_size = enc->block_size(); + const size_t ud = enc->update_granularity(); + std::vector ct; + // make room for padding + ct.resize(((pt.size() + tag_size) / block_size + 1) * block_size); + // set key & iv + assert_true(enc->set_key(key.data(), key.size())); + assert_true(enc->set_iv(iv.data(), iv.size())); + if (!ad.empty()) { + assert_true(enc->set_ad(ad.data(), ad.size())); + } + + // encrypt all in one go + size_t output_written, input_consumed; + assert_true(enc->finish( + ct.data(), ct.size(), &output_written, pt.data(), pt.size(), &input_consumed)); + ct.resize(output_written); + assert_memory_equal(ct.data(), expected_ct.data(), expected_ct.size()); + + // start over + enc.reset(Cipher::encryption(alg, mode, tag_size, disable_padding).release()); + assert_true(enc->set_key(key.data(), key.size())); + assert_true(enc->set_iv(iv.data(), iv.size())); + if (!ad.empty()) { + assert_true(enc->set_ad(ad.data(), ad.size())); + } + ct.clear(); + ct.resize(((pt.size() + tag_size) / block_size + 1) * block_size); + // encrypt in pieces + assert_memory_not_equal(ct.data(), expected_ct.data(), expected_ct.size()); + // all except the last block + size_t nonfinal_bytes = rnp_round_up(pt.size(), ud) - ud; + output_written = 0; + input_consumed = 0; + size_t written, consumed; + while (input_consumed != nonfinal_bytes) { + assert_true(enc->update(ct.data() + output_written, + ct.size() - output_written, + &written, + pt.data() + input_consumed, + ud, + &consumed)); + output_written += written; + input_consumed += consumed; + } + assert_true(enc->finish(ct.data() + output_written, + ct.size() - output_written, + &written, + pt.data() + input_consumed, + pt.size() - input_consumed, + &consumed)); + output_written += written; + ct.resize(output_written); + assert_int_equal(ct.size(), expected_ct.size()); + assert_memory_equal(ct.data(), expected_ct.data(), expected_ct.size()); + enc.reset(); + + // decrypt + auto dec = Cipher::decryption(alg, mode, tag_size, disable_padding); + assert_true(dec->set_key(key.data(), key.size())); + assert_true(dec->set_iv(iv.data(), iv.size())); + if (!ad.empty()) { + assert_true(dec->set_ad(ad.data(), ad.size())); + } + // decrypt in pieces + std::vector decrypted(ct.size()); + // all except the last block + nonfinal_bytes = rnp_round_up(ct.size(), ud) - ud; + output_written = 0; + input_consumed = 0; + while (input_consumed != nonfinal_bytes) { + assert_true(dec->update(decrypted.data() + output_written, + decrypted.size() - output_written, + &written, + (const uint8_t *) ct.data() + input_consumed, + ud, + &consumed)); + output_written += written; + input_consumed += consumed; + } + assert_true(dec->finish(decrypted.data() + output_written, + decrypted.size() - output_written, + &written, + (const uint8_t *) ct.data() + input_consumed, + ct.size() - input_consumed, + &consumed)); + output_written += written; + decrypted.resize(output_written); + assert_int_equal(decrypted.size(), pt.size()); + assert_memory_equal(decrypted.data(), pt.data(), pt.size()); + + // decrypt with a bad tag + if (tag_size) { + dec.reset(Cipher::decryption(alg, mode, tag_size, disable_padding).release()); + assert_true(dec->set_key(key.data(), key.size())); + assert_true(dec->set_iv(iv.data(), iv.size())); + if (!ad.empty()) { + assert_true(dec->set_ad(ad.data(), ad.size())); + } + // decrypt in pieces + std::vector decrypted(ct.size()); + // all except the last block + nonfinal_bytes = rnp_round_up(ct.size(), ud) - ud; + output_written = 0; + input_consumed = 0; + while (input_consumed != nonfinal_bytes) { + assert_true(dec->update(decrypted.data() + output_written, + decrypted.size() - output_written, + &written, + (const uint8_t *) ct.data() + input_consumed, + ud, + &consumed)); + output_written += written; + input_consumed += consumed; + } + // tamper with the tag + ct.back() ^= 0xff; + assert_false(dec->finish(decrypted.data() + output_written, + decrypted.size() - output_written, + &written, + (const uint8_t *) ct.data() + input_consumed, + ct.size() - input_consumed, + &consumed)); + } +} + +TEST_F(rnp_tests, test_cipher_idea) +{ + // OpenSSL do_crypt man page example + test_cipher(PGP_SA_IDEA, + PGP_CIPHER_MODE_CBC, + 0, + false, + "000102030405060708090a0b0c0d0e0f", + "0102030405060708", + NULL, + "536f6d652043727970746f2054657874", + "8974b718d0cb68b44e27c480546dfcc7a33895f461733219"); +} + +TEST_F(rnp_tests, test_cipher_aes_128_ocb) +{ + // RFC 7253 + test_cipher(PGP_SA_AES_128, + PGP_CIPHER_MODE_OCB, + 16, + false, + "000102030405060708090A0B0C0D0E0F", + "BBAA99887766554433221104", + "000102030405060708090A0B0C0D0E0F", + "000102030405060708090A0B0C0D0E0F", + "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358"); +} + +TEST_F(rnp_tests, test_cipher_aes_128_cbc) +{ + // botan test vectors + test_cipher(PGP_SA_AES_128, + PGP_CIPHER_MODE_CBC, + 0, + false, + "10d6f8e78c0ccf8736e4307aaf5b07ef", + "3eb182d95bbd5a609aecfb59a0ca898b", + NULL, + "3a", + "a7d290687ae325054a8691014d6821d7"); + test_cipher(PGP_SA_AES_128, + PGP_CIPHER_MODE_CBC, + 0, + false, + "10d6f8e78c0ccf8736e4307aaf5b07ef", + "3eb182d95bbd5a609aecfb59a0ca898b", + NULL, + "3a513eb569a503b4413b31fa883ddc88", + "0cbaf4fa94df265fe264633a994bc25fc7654f19c282a3e2db81499c941ca2b3"); +} + +TEST_F(rnp_tests, test_cipher_aes_128_cbc_nopadding) +{ + // botan test vectors + test_cipher(PGP_SA_AES_128, + PGP_CIPHER_MODE_CBC, + 0, + true, + "1f8e4973953f3fb0bd6b16662e9a3c17", + "2fe2b333ceda8f98f4a99b40d2cd34a8", + NULL, + "45cf12964fc824ab76616ae2f4bf0822", + "0f61c4d44c5147c03c195ad7e2cc12b2"); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli_common.py thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli_common.py --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli_common.py 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli_common.py 2022-04-15 07:49:21.000000000 +0000 @@ -4,9 +4,7 @@ import string import logging import os -import platform import re -from os import path from subprocess import Popen, PIPE RNP_ROOT = None @@ -15,7 +13,7 @@ class CLIError(Exception): def __init__(self, message, log = None): - super(Exception, self).__init__(message) + super(CLIError, self).__init__(message) self.log = log def __str__(self): @@ -84,10 +82,10 @@ def rnp_file_path(relpath, check = True): global RNP_ROOT if not RNP_ROOT: - pypath = path.dirname(__file__) - RNP_ROOT = path.realpath(path.join(pypath, '../..')) + pypath = os.path.dirname(__file__) + RNP_ROOT = os.path.realpath(os.path.join(pypath, '../..')) - fpath = path.realpath(path.join(RNP_ROOT, relpath)) + fpath = os.path.realpath(os.path.join(RNP_ROOT, relpath)) if check and not os.path.isfile(fpath): raise NameError('rnp: file ' + relpath + ' not found') diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli.cpp 2022-04-15 07:49:21.000000000 +0000 @@ -193,40 +193,36 @@ static bool test_cli_g10_key_sign(const char *userid) { - int ret; - /* create signature */ - ret = call_rnp("rnp", - "--homedir", - G10KEYS, - "--password", - "password", - "-u", - userid, - "-s", - FILES "/hello.txt", - NULL); + int ret = call_rnp("rnp", + "--homedir", + G10KEYS, + "--password", + "password", + "-u", + userid, + "-s", + FILES "/hello.txt", + NULL); if (ret) { + rnp_unlink(FILES "/hello.txt.pgp"); return false; } /* verify back */ ret = call_rnp("rnp", "--homedir", G10KEYS, "-v", FILES "/hello.txt.pgp", NULL); - if (ret) { - return false; - } rnp_unlink(FILES "/hello.txt.pgp"); - return true; + return !ret; } static bool test_cli_g10_key_encrypt(const char *userid) { - int ret; - /* encrypt */ - ret = call_rnp("rnp", "--homedir", G10KEYS, "-r", userid, "-e", FILES "/hello.txt", NULL); + int ret = + call_rnp("rnp", "--homedir", G10KEYS, "-r", userid, "-e", FILES "/hello.txt", NULL); if (ret) { + rnp_unlink(FILES "/hello.txt.pgp"); return false; } @@ -239,11 +235,8 @@ "-d", FILES "/hello.txt.pgp", NULL); - if (ret) { - return false; - } rnp_unlink(FILES "/hello.txt.pgp"); - return true; + return !ret; } TEST_F(rnp_tests, test_cli_g10_operations) @@ -282,11 +275,18 @@ assert_false(test_cli_g10_key_sign("02a5715c3537717e")); // fail - encrypting subkey assert_true(test_cli_g10_key_encrypt("02a5715c3537717e")); // success - /* check rsa/rsa key, key is SC while subkey is E */ - assert_true(test_cli_g10_key_sign("2fb9179118898e8b")); - assert_true(test_cli_g10_key_encrypt("2fb9179118898e8b")); + /* check rsa/rsa key, key is SC while subkey is E. Must fail as uses SHA1 */ + assert_false(test_cli_g10_key_sign("2fb9179118898e8b")); + assert_false(test_cli_g10_key_encrypt("2fb9179118898e8b")); assert_false(test_cli_g10_key_sign("6e2f73008f8b8d6e")); - assert_true(test_cli_g10_key_encrypt("6e2f73008f8b8d6e")); + assert_false(test_cli_g10_key_encrypt("6e2f73008f8b8d6e")); + + /* check new rsa/rsa key, key is SC while subkey is E. */ + /* Now fails since we cannot parse new S-exps */ + assert_false(test_cli_g10_key_sign("bd860a52d1899c0f")); + assert_false(test_cli_g10_key_encrypt("bd860a52d1899c0f")); + assert_false(test_cli_g10_key_sign("8e08d46a37414996")); + assert_false(test_cli_g10_key_encrypt("8e08d46a37414996")); /* check ed25519 key */ assert_true(test_cli_g10_key_sign("cc786278981b0728")); @@ -317,22 +317,22 @@ assert_true(test_cli_g10_key_encrypt("9853df2f6d297442")); /* check bp256 key */ - assert_true(test_cli_g10_key_sign("d0c8a3daf9e0634a")); - assert_true(test_cli_g10_key_encrypt("d0c8a3daf9e0634a")); + assert_true(test_cli_g10_key_sign("d0c8a3daf9e0634a") == brainpool_enabled()); + assert_true(test_cli_g10_key_encrypt("d0c8a3daf9e0634a") == brainpool_enabled()); assert_false(test_cli_g10_key_sign("2edabb94d3055f76")); - assert_true(test_cli_g10_key_encrypt("2edabb94d3055f76")); + assert_true(test_cli_g10_key_encrypt("2edabb94d3055f76") == brainpool_enabled()); /* check bp384 key */ - assert_true(test_cli_g10_key_sign("6cf2dce85599ada2")); - assert_true(test_cli_g10_key_encrypt("6cf2dce85599ada2")); + assert_true(test_cli_g10_key_sign("6cf2dce85599ada2") == brainpool_enabled()); + assert_true(test_cli_g10_key_encrypt("6cf2dce85599ada2") == brainpool_enabled()); assert_false(test_cli_g10_key_sign("cff1bb6f16d28191")); - assert_true(test_cli_g10_key_encrypt("cff1bb6f16d28191")); + assert_true(test_cli_g10_key_encrypt("cff1bb6f16d28191") == brainpool_enabled()); /* check bp512 key */ - assert_true(test_cli_g10_key_sign("aa5c58d14f7b8f48")); - assert_true(test_cli_g10_key_encrypt("aa5c58d14f7b8f48")); + assert_true(test_cli_g10_key_sign("aa5c58d14f7b8f48") == brainpool_enabled()); + assert_true(test_cli_g10_key_encrypt("aa5c58d14f7b8f48") == brainpool_enabled()); assert_false(test_cli_g10_key_sign("20cdaa1482ba79ce")); - assert_true(test_cli_g10_key_encrypt("20cdaa1482ba79ce")); + assert_true(test_cli_g10_key_encrypt("20cdaa1482ba79ce") == brainpool_enabled()); /* check secp256k1 key */ assert_true(test_cli_g10_key_sign("3ea5bb6f9692c1a0")); @@ -662,6 +662,8 @@ expiration, "--userid", userid, + "--s2k-iterations", + "65536", "--numbits", "1024", NULL); @@ -688,6 +690,8 @@ tm2100.tm_mday = 1; tm2100.tm_mon = 0; tm2100.tm_year = 200; + /* line below is required to correctly handle DST changes */ + tm2100.tm_isdst = -1; expected_diff_beyond2038_absolute = mktime(&tm2100) - basetime; } struct tm *timeinfo = localtime(&rawtime); @@ -726,7 +730,7 @@ assert_int_not_equal(key_generate(GENKEYS, "expiration_overflow@rnp", "200y"), 0); assert_int_not_equal(key_generate(GENKEYS, "expiration_past@rnp", "2021-01-01"), 0); - // these should pass and go to the keystore -- 15 primary keys and 15 subkeys + // these should pass and go to the keystore -- 17 primary keys and 17 subkeys assert_int_equal(key_generate(GENKEYS, "expiration_beyond2038_relative@rnp", "20y"), 0); assert_int_equal(key_generate(GENKEYS, "expiration_beyond2038_absolute@rnp", "2100-01-01"), 0); @@ -746,7 +750,7 @@ assert_int_equal(key_generate(GENKEYS, "expiration_2months@rnp", "2m"), 0); assert_int_equal(key_generate(GENKEYS, "expiration_2years@rnp", "2y"), 0); - auto keystore = new rnp_key_store_t(PGP_KEY_STORE_GPG, ""); + auto keystore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); pgp_source_t src = {}; assert_rnp_success(init_file_src(&src, GENKEYS "/pubring.gpg")); assert_true(rnp_key_store_load_from_src(keystore, &src, NULL)); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli_perf.py thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli_perf.py --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli_perf.py 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli_perf.py 2022-04-15 07:49:22.000000000 +0000 @@ -6,7 +6,6 @@ import inspect import os import logging -from os import path from timeit import default_timer as perf_timer from argparse import ArgumentParser from cli_common import ( @@ -52,8 +51,8 @@ logging.debug('Setting up test in {} ...'.format(WORKDIR)) # Creating working directory and populating it with test files - RNPDIR = path.join(WORKDIR, '.rnp') - GPGDIR = path.join(WORKDIR, '.gpg') + RNPDIR = os.path.join(WORKDIR, '.rnp') + GPGDIR = os.path.join(WORKDIR, '.gpg') os.mkdir(RNPDIR, 0o700) os.mkdir(GPGDIR, 0o700) @@ -62,25 +61,25 @@ params = ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', 'performance@rnp', '--generate-key'] # Run key generation - ret, out, err = run_proc(RNPK, params) + run_proc(RNPK, params) os.close(pipe) + # Importing keys to GnuPG so it can build trustdb and so on - ret, out, err = run_proc(GPG, ['--batch', '--passphrase', '', '--homedir', GPGDIR, - '--import', path.join(RNPDIR, 'pubring.gpg'), - path.join(RNPDIR, 'secring.gpg')]) + run_proc(GPG, ['--batch', '--passphrase', '', '--homedir', GPGDIR, '--import', + os.path.join(RNPDIR, 'pubring.gpg'), os.path.join(RNPDIR, 'secring.gpg')]) # Generating small file for tests SMALLSIZE = 3312 st = 'lorem ipsum dol ' * (SMALLSIZE//16+1) - with open(path.join(WORKDIR, SMALLFILE), 'w+') as small_file: + with open(os.path.join(WORKDIR, SMALLFILE), 'w+') as small_file: small_file.write(st) # Generating large file for tests print('Generating large file of size {}'.format(size_to_readable(LARGESIZE))) st = '0123456789ABCDEF' * (1024//16) - with open(path.join(WORKDIR, LARGEFILE), 'w') as fd: + with open(os.path.join(WORKDIR, LARGEFILE), 'w') as fd: for i in range(0, LARGESIZE // 1024): fd.write(st) @@ -168,9 +167,9 @@ infile, outfile, iterations, fsize = (LARGEFILE, LARGEFILE + '.gpg', LARGE_ITERATIONS, LARGESIZE) - infile = path.join(WORKDIR, infile) - rnpout = path.join(WORKDIR, outfile + '.rnp') - gpgout = path.join(WORKDIR, outfile + '.gpg') + infile = os.path.join(WORKDIR, infile) + rnpout = os.path.join(WORKDIR, outfile + '.rnp') + gpgout = os.path.join(WORKDIR, outfile + '.gpg') return (infile, rnpout, gpgout, iterations, fsize) @@ -313,5 +312,5 @@ try: shutil.rmtree(WORKDIR) - except: + except Exception: logging.info(("Cleanup failed")) diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli_tests.py thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli_tests.py --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/cli_tests.py 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/cli_tests.py 2022-04-15 07:49:22.000000000 +0000 @@ -1,15 +1,14 @@ #!/usr/bin/env python -import itertools import logging import os +import os.path import re import shutil import sys import tempfile import time import unittest -from os import path from platform import architecture import cli_common @@ -28,10 +27,17 @@ GPGHOME = None PASSWORD = 'password' RMWORKDIR = True +GPG_AEAD = False +GPG_NO_OLD = False TESTS_SUCCEEDED = [] TESTS_FAILED = [] TEST_WORKFILES = [] +# Supported features +RNP_TWOFISH = True +RNP_BRAINPOOL = True +RNP_AEAD = True + if sys.version_info >= (3,): unichr = chr @@ -72,7 +78,32 @@ KEY_ENCRYPT = 'encryption@rnp' KEY_SIGN_RNP = 'signing@rnp' KEY_SIGN_GPG = 'signing@gpg' +KEY_ENC_RNP = 'enc@rnp' +AT_EXAMPLE = '@example.com' + +# Keyrings +PUBRING = 'pubring.gpg' +SECRING = 'secring.gpg' +PUBRING_1 = 'keyrings/1/pubring.gpg' +SECRING_G10 = 'test_stream_key_load/g10' +KEY_ALICE_PUB = 'test_key_validity/alice-pub.asc' +KEY_ALICE_SEC = 'test_key_validity/alice-sec.asc' +KEY_ALICE_SUB_SEC = 'test_key_validity/alice-sub-sec.pgp' +KEY_25519_NOTWEAK_SEC = 'test_key_edge_cases/key-25519-non-tweaked-sec.asc' + +# Messages +MSG_TXT = 'test_messages/message.txt' +MSG_ES_25519 = 'test_messages/message.txt.enc-sign-25519' + +# Extensions +EXT_SIG = '.txt.sig' +EXT_ASC = '.txt.asc' +EXT_PGP = '.txt.pgp' + +# Misc +GPG_LOOPBACK = '--pinentry-mode=loopback' +# Regexps RE_RSA_KEY = r'(?s)^' \ r'# .*' \ r':public key packet:\s+' \ @@ -158,6 +189,8 @@ r'Total number processed: 1.*' \ r'new key revocations: 1.*$' +RE_SIG_1_IMPORT = r'(?s)^.*Import finished: 1 new signature, 0 unchanged, 0 unknown.*' + RNP_TO_GPG_ZALGS = { 'zip' : '1', 'zlib' : '2', 'bzip2' : '3' } # These are mostly identical RNP_TO_GPG_CIPHERS = {'AES' : 'aes128', 'AES192' : 'aes192', 'AES256' : 'aes256', @@ -166,6 +199,18 @@ 'IDEA' : 'idea', '3DES' : '3des', 'CAST5' : 'cast5', 'BLOWFISH' : 'blowfish'} +# Error messages +RNP_DATA_DIFFERS = 'rnp decrypted data differs' +GPG_DATA_DIFFERS = 'gpg decrypted data differs' +KEY_GEN_FAILED = 'key generation failed' +KEY_LIST_FAILED = 'key list failed' +KEY_LIST_WRONG = 'wrong key list output' +PKT_LIST_FAILED = 'packet listing failed' +ALICE_IMPORT_FAIL = 'Alice key import failed' +ENC_FAILED = 'encryption failed' +DEC_FAILED = 'decryption failed' +DEC_DIFFERS = 'Decrypted data differs' + def check_packets(fname, regexp): ret, output, err = run_proc(GPG, ['--homedir', '.', '--list-packets', path_for_gpg(fname)]) @@ -179,41 +224,6 @@ logging.debug(output) return result -def test_userid_genkey(userid_beginning, weird_part, userid_end, weird_part2=''): - clear_keyrings() - msgs = [] - log = None - USERS = [userid_beginning + weird_part + userid_end] - if weird_part2: - USERS.append(userid_beginning + weird_part2 + userid_end) - # Run key generation - for userid in USERS: - rnp_genkey_rsa(userid, 1024) - # Read with GPG - ret, out, err = run_proc(GPG, ['--homedir', path_for_gpg(RNPDIR), '--list-keys', '--charset', CONSOLE_ENCODING]) - if ret != 0: - msgs.append('gpg : failed to read keystore') - log = err - else: - tracker_escaped = re.findall(r'' + userid_beginning + '.*' + userid_end + '', out) - tracker_gpg = list(map(decode_string_escape, tracker_escaped)) - if tracker_gpg != USERS: - msgs.append('gpg : failed to find expected userids from keystore') - # Read with rnpkeys - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if ret != 0: - msgs.append('rnpkeys : failed to read keystore') - log = err - else: - tracker_escaped = re.findall(r'' + userid_beginning + '.*' + userid_end + '', out) - tracker_rnp = list(map(decode_string_escape, tracker_escaped)) - if tracker_rnp != USERS: - msgs.append('rnpkeys : failed to find expected userids from keystore') - clear_keyrings() - if msgs: - raise_err('\n'.join(msgs), log) - - def clear_keyrings(): shutil.rmtree(RNPDIR, ignore_errors=True) os.mkdir(RNPDIR, 0o700) @@ -222,7 +232,7 @@ while os.path.isdir(GPGDIR): try: shutil.rmtree(GPGDIR) - except: + except Exception: time.sleep(0.1) os.mkdir(GPGDIR, 0o700) @@ -258,14 +268,14 @@ try: for fpath in args: os.remove(fpath) - except: + except Exception: pass def reg_workfiles(mainname, *exts): global TEST_WORKFILES res = [] for ext in exts: - fpath = path.join(WORKDIR, mainname + ext) + fpath = os.path.join(WORKDIR, mainname + ext) if fpath in TEST_WORKFILES: logging.warn('Warning! Path {} is already in TEST_WORKFILES'.format(fpath)) else: @@ -279,20 +289,19 @@ for fpath in TEST_WORKFILES: try: os.remove(fpath) - except (OSError, FileNotFoundError): + except (OSError): pass TEST_WORKFILES = [] def rnp_genkey_rsa(userid, bits=2048, pswd=PASSWORD): pipe = pswd_pipe(pswd) - ret, _, err = run_proc(RNPK, ['--numbits', str(bits), '--homedir', RNPDIR, '--pass-fd', - str(pipe), '--userid', userid, '--generate-key']) + ret, _, err = run_proc(RNPK, ['--numbits', str(bits), '--homedir', RNPDIR, '--pass-fd', str(pipe), + '--notty', '--s2k-iterations', '50000', '--userid', userid, '--generate-key']) os.close(pipe) if ret != 0: raise_err('rsa key generation failed', err) - def rnp_params_insert_z(params, pos, z): if z: if len(z) > 0 and z[0] != None: @@ -316,11 +325,10 @@ params[2:2] = ['-r', escape_regex(userid)] # Passwords to encrypt to. None or [] disables password encryption. if passwords: - if recipients == None: + if recipients is None: params[2:2] = ['-c'] pipe = pswd_pipe('\n'.join(passwords)) - params[2:2] = ['--pass-fd', str(pipe)] - params[2:2] = ['--passwords', str(len(passwords))] + params[2:2] = ['--pass-fd', str(pipe), '--passwords', str(len(passwords))] # Cipher or None for default if cipher: params[2:2] = ['--cipher', cipher] @@ -444,7 +452,7 @@ def gpg_import_pubring(kpath=None): if not kpath: - kpath = path.join(RNPDIR, 'pubring.gpg') + kpath = os.path.join(RNPDIR, PUBRING) ret, _, err = run_proc( GPG, ['--display-charset', CONSOLE_ENCODING, '--batch', '--homedir', GPGHOME, '--import', kpath]) if ret != 0: @@ -453,7 +461,7 @@ def gpg_import_secring(kpath=None, password = PASSWORD): if not kpath: - kpath = path.join(RNPDIR, 'secring.gpg') + kpath = os.path.join(RNPDIR, SECRING) ret, _, err = run_proc( GPG, ['--display-charset', CONSOLE_ENCODING, '--batch', '--passphrase', password, '--homedir', GPGHOME, '--import', kpath]) if ret != 0: @@ -461,7 +469,7 @@ def gpg_export_secret_key(userid, password, keyfile): - ret, _, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--pinentry-mode=loopback', + ret, _, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, GPG_LOOPBACK, '--yes', '--passphrase', password, '--output', path_for_gpg(keyfile), '--export-secret-key', userid]) @@ -483,12 +491,12 @@ if z: gpg_params_insert_z(params, 3, z) if cipher: params[3:3] = ['--cipher-algo', RNP_TO_GPG_CIPHERS[cipher]] if armor: params[2:2] = ['--armor'] + if GPG_NO_OLD: params[2:2] = ['--allow-old-cipher-algos'] ret, out, err = run_proc(GPG, params) if ret != 0: raise_err('gpg encryption failed for cipher ' + cipher, err) - def gpg_symencrypt_file(src, dst, cipher=None, z=None, armor=False, aead=None): src = path_for_gpg(src) dst = path_for_gpg(dst) @@ -496,6 +504,7 @@ '--passphrase', PASSWORD, '--output', dst, src] if z: gpg_params_insert_z(params, 3, z) if cipher: params[3:3] = ['--cipher-algo', RNP_TO_GPG_CIPHERS[cipher]] + if GPG_NO_OLD: params[3:3] = ['--allow-old-cipher-algos'] if armor: params[2:2] = ['--armor'] if aead != None: if len(aead) > 0 and aead[0] != None: @@ -512,7 +521,7 @@ def gpg_decrypt_file(src, dst, keypass): src = path_for_gpg(src) dst = path_for_gpg(dst) - ret, out, err = run_proc(GPG, ['--display-charset', CONSOLE_ENCODING, '--homedir', GPGHOME, '--pinentry-mode=loopback', '--batch', + ret, out, err = run_proc(GPG, ['--display-charset', CONSOLE_ENCODING, '--homedir', GPGHOME, GPG_LOOPBACK, '--batch', '--yes', '--passphrase', keypass, '--trust-model', 'always', '-o', dst, '-d', src]) if ret != 0: @@ -566,7 +575,7 @@ def gpg_sign_file(src, dst, signer, z=None, armor=False): src = path_for_gpg(src) dst = path_for_gpg(dst) - params = ['--homedir', GPGHOME, '--pinentry-mode=loopback', '--batch', '--yes', + params = ['--homedir', GPGHOME, GPG_LOOPBACK, '--batch', '--yes', '--passphrase', PASSWORD, '--trust-model', 'always', '-u', signer, '-o', dst, '-s', src] if z: gpg_params_insert_z(params, 3, z) @@ -578,7 +587,7 @@ def gpg_sign_detached(src, signer, armor=False, textsig=False): src = path_for_gpg(src) - params = ['--homedir', GPGHOME, '--pinentry-mode=loopback', '--batch', '--yes', + params = ['--homedir', GPGHOME, GPG_LOOPBACK, '--batch', '--yes', '--passphrase', PASSWORD, '--trust-model', 'always', '-u', signer, '--detach-sign', src] if armor: params.insert(2, '--armor') @@ -591,7 +600,7 @@ def gpg_sign_cleartext(src, dst, signer): src = path_for_gpg(src) dst = path_for_gpg(dst) - params = ['--homedir', GPGHOME, '--pinentry-mode=loopback', '--batch', '--yes', '--passphrase', + params = ['--homedir', GPGHOME, GPG_LOOPBACK, '--batch', '--yes', '--passphrase', PASSWORD, '--trust-model', 'always', '-u', signer, '-o', dst, '--clearsign', src] ret, _, err = run_proc(GPG, params) if ret != 0: @@ -599,7 +608,7 @@ def gpg_agent_clear_cache(): - run_proc(GPGCONF, ['--display-charset', CONSOLE_ENCODING, '--homedir', GPGHOME, '--kill', 'gpg-agent']) + run_proc(GPGCONF, ['--homedir', GPGHOME, '--kill', 'gpg-agent']) ''' Things to try here later on: @@ -622,7 +631,7 @@ gpg_encrypt_file(src, dst, cipher, z, armor) # Decrypt encrypted file with RNP rnp_decrypt_file(dst, dec) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) remove_files(dst, dec) clear_workfiles() @@ -641,11 +650,11 @@ rnp_encrypt_file_ex(src, enc, [KEY_ENCRYPT], None, None, None, z, armor) # Decrypt encrypted file with GPG gpg_decrypt_file(enc, dst, PASSWORD) - compare_files(src, dst, 'gpg decrypted data differs') + compare_files(src, dst, GPG_DATA_DIFFERS) remove_files(dst) # Decrypt encrypted file with RNP rnp_decrypt_file(enc, dst) - compare_files(src, dst, 'rnp decrypted data differs') + compare_files(src, dst, RNP_DATA_DIFFERS) remove_files(enc, dst) clear_workfiles() @@ -665,7 +674,7 @@ gpg_symencrypt_file(src, dst, cipher, z, armor) # Decrypt encrypted file with RNP rnp_decrypt_file(dst, dec) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) remove_files(dst, dec) clear_workfiles() @@ -679,11 +688,11 @@ rnp_encrypt_file_ex(src, enc, None, [PASSWORD], None, cipher, z, armor) # Decrypt encrypted file with GPG gpg_decrypt_file(enc, dst, PASSWORD) - compare_files(src, dst, 'gpg decrypted data differs') + compare_files(src, dst, GPG_DATA_DIFFERS) remove_files(dst) # Decrypt encrypted file with RNP rnp_decrypt_file(enc, dst) - compare_files(src, dst, 'rnp decrypted data differs') + compare_files(src, dst, RNP_DATA_DIFFERS) remove_files(enc, dst) clear_workfiles() @@ -695,19 +704,19 @@ rnp_encrypt_file_ex(src, enc, None, [PASSWORD], aead, cipher, z) # Decrypt encrypted file with RNP rnp_decrypt_file(enc, dst) - compare_files(src, dst, 'rnp decrypted data differs') + compare_files(src, dst, RNP_DATA_DIFFERS) remove_files(dst) if usegpg: # Decrypt encrypted file with GPG gpg_decrypt_file(enc, dst, PASSWORD) - compare_files(src, dst, 'gpg decrypted data differs') + compare_files(src, dst, GPG_DATA_DIFFERS) remove_files(dst, enc) # Encrypt cleartext file with GPG gpg_symencrypt_file(src, enc, cipher, z, False, aead) # Decrypt encrypted file with RNP rnp_decrypt_file(enc, dst) - compare_files(src, dst, 'rnp decrypted data differs') + compare_files(src, dst, RNP_DATA_DIFFERS) clear_workfiles() @@ -730,7 +739,7 @@ def rnp_detached_signing_rnp_to_gpg(filesize): - src, sig, asc = reg_workfiles('cleartext', '.txt', '.txt.sig', '.txt.asc') + src, sig, asc = reg_workfiles('cleartext', '.txt', EXT_SIG, EXT_ASC) # Generate random file of required size random_text(src, filesize) for armor in [True, False]: @@ -746,7 +755,7 @@ def rnp_cleartext_signing_rnp_to_gpg(filesize): - src, asc = reg_workfiles('cleartext', '.txt', '.txt.asc') + src, asc = reg_workfiles('cleartext', '.txt', EXT_ASC) # Generate random file of required size random_text(src, filesize) # Sign file with RNP @@ -773,7 +782,7 @@ def rnp_detached_signing_gpg_to_rnp(filesize, textsig=False): - src, sig, asc = reg_workfiles('cleartext', '.txt', '.txt.sig', '.txt.asc') + src, sig, asc = reg_workfiles('cleartext', '.txt', EXT_SIG, EXT_ASC) # Generate random file of required size random_text(src, filesize) for armor in [True, False]: @@ -785,7 +794,7 @@ clear_workfiles() def rnp_cleartext_signing_gpg_to_rnp(filesize): - src, asc = reg_workfiles('cleartext', '.txt', '.txt.asc') + src, asc = reg_workfiles('cleartext', '.txt', EXT_ASC) # Generate random file of required size random_text(src, filesize) # Sign file with GPG @@ -796,12 +805,40 @@ gpg_verify_cleartext(asc, KEY_SIGN_GPG) clear_workfiles() -def gpg_supports_aead(): - ret, out, err = run_proc(GPG, ["--version"]) - if re.match(r'(?s)^.*AEAD:\s+EAX,\s+OCB.*', out): - return True - else: - return False +def gpg_check_features(): + global GPG_AEAD, GPG_NO_OLD + _, out, _ = run_proc(GPG, ["--version"]) + # AEAD + GPG_AEAD = re.match(r'(?s)^.*AEAD:\s+EAX,\s+OCB.*', out) + # Version 2.3.0-beta1598 and up drops support of 64-bit block algos + match = re.match(r'(?s)^.*gpg \(GnuPG\) ([0-9]+)\.([0-9]+)\.([0-9]+)(-beta([0-9]+))?.*$', out) + if not match: + raise_err('Failed to parse GnuPG version.') + # Version < 2.3.0 + if (int(match.group(1)) < 2) or ((int(match.group(1)) == 2) and (int(match.group(2)) < 3)): + GPG_NO_OLD = False + return + # Version > 2.3.0 + if (int(match.group(1)) > 2) or (int(match.group(2)) > 3) or (int(match.group(3)) > 0): + GPG_NO_OLD = True + return + # Version 2.3.0 release or beta + GPG_NO_OLD = not match.group(5) or (int(match.group(5)) >= 1598) + +def rnp_check_features(): + global RNP_TWOFISH, RNP_BRAINPOOL, RNP_AEAD + ret, out, _ = run_proc(RNP, ['--version']) + if ret != 0: + raise_err('Failed to get RNP version.') + # AEAD + RNP_AEAD = re.match(r'(?s)^.*AEAD:.*EAX,.*OCB.*', out) + # Twofish + RNP_TWOFISH = re.match(r'(?s)^.*Encryption:.*TWOFISH.*', out) + # Brainpool curves + RNP_BRAINPOOL = re.match(r'(?s)^.*Curves:.*brainpoolP256r1.*brainpoolP384r1.*brainpoolP512r1.*', out) + # Check that everything is enabled for Botan: + if re.match(r'(?s)^.*Backend:\s+Botan.*', out) and (not RNP_AEAD or not RNP_TWOFISH or not RNP_BRAINPOOL): + raise_err('Something is wrong with features detection.') def setup(loglvl): # Setting up directories. @@ -814,7 +851,7 @@ logging.info('Running in ' + WORKDIR) cli_common.WORKDIR = WORKDIR - RNPDIR = path.join(WORKDIR, '.rnp') + RNPDIR = os.path.join(WORKDIR, '.rnp') RNP = os.getenv('RNP_TESTS_RNP_PATH') or 'rnp' RNPK = os.getenv('RNP_TESTS_RNPKEYS_PATH') or 'rnpkeys' shutil.rmtree(RNPDIR, ignore_errors=True) @@ -822,10 +859,12 @@ os.environ["RNP_LOG_CONSOLE"] = "1" - GPGDIR = path.join(WORKDIR, '.gpg') + GPGDIR = os.path.join(WORKDIR, '.gpg') GPGHOME = path_for_gpg(GPGDIR) if is_windows() else GPGDIR GPG = os.getenv('RNP_TESTS_GPG_PATH') or find_utility('gpg') GPGCONF = os.getenv('RNP_TESTS_GPGCONF_PATH') or find_utility('gpgconf') + gpg_check_features() + rnp_check_features() shutil.rmtree(GPGDIR, ignore_errors=True) os.mkdir(GPGDIR, 0o700) @@ -890,8 +929,7 @@ def tearDown(self): clear_workfiles() - @staticmethod - def _rnpkey_generate_rsa(bits= None): + def _rnpkey_generate_rsa(self, bits= None): # Setup command line params if bits: params = ['--numbits', str(bits)] @@ -903,46 +941,71 @@ # Open pipe for password pipe = pswd_pipe(PASSWORD) params = params + ['--homedir', RNPDIR, '--pass-fd', str(pipe), - '--userid', userid, '--generate-key'] + '--userid', userid, '--s2k-iterations', '50000', '--generate-key'] # Run key generation - ret, out, err = run_proc(RNPK, params) + ret, _, _ = run_proc(RNPK, params) os.close(pipe) - if ret != 0: - raise_err('key generation failed', err) + self.assertEqual(ret, 0, KEY_GEN_FAILED) # Check packets using the gpg - match = check_packets(path.join(RNPDIR, 'pubring.gpg'), RE_RSA_KEY) - if not match: - raise_err('generated key check failed') + match = check_packets(os.path.join(RNPDIR, PUBRING), RE_RSA_KEY) + self.assertTrue(match, 'generated key check failed') keybits = int(match.group(1)) - if keybits > bits or keybits <= bits - 8: - raise_err('wrong key bits') + self.assertLessEqual(keybits, bits, 'too much bits') + self.assertGreater(keybits, bits - 8, 'too few bits') keyid = match.group(2) - if not match.group(3) == userid: - raise_err('wrong user id') + self.assertEqual(match.group(3), userid, 'wrong user id') # List keys using the rnpkeys - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if ret != 0: - raise_err('key list failed', err) + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0, KEY_LIST_FAILED) match = re.match(RE_RSA_KEY_LIST, out) # Compare key ids - if not match: - raise_err('wrong key list output', out) - if not match.group(3)[-16:] == match.group(2) or not match.group(2) == keyid.lower(): - raise_err('wrong key ids') - if not match.group(1) == str(bits): - raise_err('wrong key bits in list') + self.assertTrue(match, 'wrong RSA key list output') + self.assertEqual(match.group(3)[-16:], match.group(2), 'wrong fp') + self.assertEqual(match.group(2), keyid.lower(), 'wrong keyid') + self.assertEqual(match.group(1), str(bits), 'wrong key bits in list') # Import key to the gnupg - ret, out, err = run_proc(GPG, ['--batch', '--passphrase', PASSWORD, '--homedir', + ret, _, _ = run_proc(GPG, ['--batch', '--passphrase', PASSWORD, '--homedir', GPGHOME, '--import', - path_for_gpg(path.join(RNPDIR, 'pubring.gpg')), - path_for_gpg(path.join(RNPDIR, 'secring.gpg'))]) - if ret != 0: - raise_err('gpg key import failed', err) + path_for_gpg(os.path.join(RNPDIR, PUBRING)), + path_for_gpg(os.path.join(RNPDIR, SECRING))]) + self.assertEqual(ret, 0, 'gpg key import failed') # Cleanup and return clear_keyrings() def test_generate_default_rsa_key(self): - Keystore._rnpkey_generate_rsa() + self._rnpkey_generate_rsa() + + def test_rnpkeys_keygen_invalid_parameters(self): + # Pass invalid numbits + ret, _, err = run_proc(RNPK, ['--numbits', 'wrong', '--homedir', RNPDIR, '--password', 'password', + '--userid', 'wrong', '--generate-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*wrong bits value: wrong.*') + # Too small + ret, _, err = run_proc(RNPK, ['--numbits', '768', '--homedir', RNPDIR, '--password', 'password', + '--userid', '768', '--generate-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*wrong bits value: 768.*') + # Wrong hash algorithm + ret, _, err = run_proc(RNPK, ['--hash', 'BAD_HASH', '--homedir', RNPDIR, '--password', 'password', + '--userid', 'bad_hash', '--generate-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Unsupported hash algorithm: BAD_HASH.*') + # Wrong S2K iterations + ret, _, err = run_proc(RNPK, ['--s2k-iterations', 'WRONG_ITER', '--homedir', RNPDIR, '--password', 'password', + '--userid', 'wrong_iter', '--generate-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Wrong iterations value: WRONG_ITER.*') + # Wrong S2K msec + ret, _, err = run_proc(RNPK, ['--s2k-msec', 'WRONG_MSEC', '--homedir', RNPDIR, '--password', 'password', + '--userid', 'wrong_msec', '--generate-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Invalid s2k msec value: WRONG_MSEC.*') + # Wrong cipher + ret, _, err = run_proc(RNPK, ['--cipher', 'WRONG_AES', '--homedir', RNPDIR, '--password', 'password', + '--userid', 'wrong_aes', '--generate-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Unsupported symmetric algorithm: WRONG_AES.*') def test_generate_multiple_rsa_key__check_if_available(self): ''' @@ -954,30 +1017,23 @@ # generate the next key pipe = pswd_pipe(PASSWORD) userid = str(i) + '@rnp-multiple' - ret, out, err = run_proc(RNPK, ['--numbits', '2048', '--homedir', RNPDIR, - '--pass-fd', str(pipe), '--userid', userid, - '--generate-key']) + ret, _, _ = run_proc(RNPK, ['--numbits', '2048', '--homedir', RNPDIR, '--s2k-msec', '100', + '--cipher', 'AES-128', '--pass-fd', str(pipe), '--userid', userid, + '--generate-key']) os.close(pipe) - if ret != 0: - raise_err('key generation failed', err) + self.assertEqual(ret, 0, KEY_GEN_FAILED) # list keys using the rnpkeys, checking whether it reports correct key # number - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if ret != 0: - raise_err('key list failed', err) + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0, KEY_LIST_FAILED) match = re.match(RE_MULTIPLE_KEY_LIST, out) - if not match: - raise_err('wrong key list output', out) - if not match.group(1) == str((i + 1) * 2): - raise_err('wrong key count', out) + self.assertTrue(match, KEY_LIST_WRONG) + self.assertEqual(match.group(1), str((i + 1) * 2), 'wrong key count') # Checking the 5 keys output - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if ret != 0: - raise_err('key list failed', err) - match = re.match(RE_MULTIPLE_KEY_5, out) - if not match: - raise_err('wrong key list output', out) + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0, KEY_LIST_FAILED) + self.assertRegex(out, RE_MULTIPLE_KEY_5, KEY_LIST_WRONG) # Cleanup and return clear_keyrings() @@ -987,45 +1043,34 @@ Generate key with GnuPG and import it to rnp ''' # Generate key in GnuPG - ret, out, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--passphrase', + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--passphrase', '', '--quick-generate-key', 'rsakey@gpg', 'rsa']) - if ret != 0: - raise_err('gpg key generation failed, error ' + str(ret) , err) + self.assertEqual(ret, 0, 'gpg key generation failed') # Getting fingerprint of the generated key - ret, out, err = run_proc( - GPG, ['--batch', '--homedir', GPGHOME, '--list-keys']) + ret, out, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--list-keys']) match = re.match(RE_GPG_SINGLE_RSA_KEY, out) - if not match: - raise_err('wrong gpg key list output', out) + self.assertTrue(match, 'wrong gpg key list output') keyfp = match.group(1) # Exporting generated public key ret, out, err = run_proc( GPG, ['--batch', '--homedir', GPGHOME, '--armor', '--export', keyfp]) - if ret != 0: - raise_err('gpg : public key export failed', err) - pubpath = path.join(RNPDIR, keyfp + '-pub.asc') + self.assertEqual(ret, 0, 'gpg : public key export failed') + pubpath = os.path.join(RNPDIR, keyfp + '-pub.asc') with open(pubpath, 'w+') as f: f.write(out) # Exporting generated secret key ret, out, err = run_proc( GPG, ['--batch', '--homedir', GPGHOME, '--armor', '--export-secret-key', keyfp]) - if ret != 0: - raise_err('gpg : secret key export failed', err) - secpath = path.join(RNPDIR, keyfp + '-sec.asc') + self.assertEqual(ret, 0, 'gpg : secret key export failed') + secpath = os.path.join(RNPDIR, keyfp + '-sec.asc') with open(secpath, 'w+') as f: f.write(out) # Importing public key to rnp - ret, out, err = run_proc( - RNPK, ['--homedir', RNPDIR, '--import-key', pubpath]) - if ret != 0: - raise_err('rnp : public key import failed', err) + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-key', pubpath]) + self.assertEqual(ret, 0, 'rnp : public key import failed') # Importing secret key to rnp - ret, out, err = run_proc( - RNPK, ['--homedir', RNPDIR, '--import-key', secpath]) - if ret != 0: - raise_err('rnp : secret key import failed', err) - # We do not check keyrings after the import - imported by RNP keys are not - # saved yet + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-key', secpath]) + self.assertEqual(ret, 0, 'rnp : secret key import failed') def test_generate_with_rnp_import_to_gpg(self): ''' @@ -1034,20 +1079,20 @@ # Open pipe for password pipe = pswd_pipe(PASSWORD) # Run key generation - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', 'rsakey@rnp', '--generate-key']) os.close(pipe) - if ret != 0: raise_err('key generation failed', err) + self.assertEqual(ret, 0, KEY_GEN_FAILED) # Export key - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'rsakey@rnp']) - if ret != 0: raise_err('key export failed', err) - pubpath = path.join(RNPDIR, 'rnpkey-pub.asc') + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'rsakey@rnp']) + self.assertEqual(ret, 0, 'key export failed') + pubpath = os.path.join(RNPDIR, 'rnpkey-pub.asc') with open(pubpath, 'w+') as f: f.write(out) # Import key with GPG - ret, out, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', path_for_gpg(pubpath)]) - if ret != 0: raise_err('gpg : public key import failed', err) + self.assertEqual(ret, 0, 'gpg : public key import failed') def test_generate_to_kbx(self): ''' @@ -1061,11 +1106,11 @@ '--userid', kbx_userid_tracker, '--homedir', RNPDIR, '--pass-fd', str(pipe)]) os.close(pipe) - if ret != 0: raise_err('key generation failed', err) + self.assertEqual(ret, 0, KEY_GEN_FAILED) # Read KBX with GPG ret, out, err = run_proc(GPG, ['--homedir', path_for_gpg(RNPDIR), '--list-keys']) - if ret != 0: raise_err('gpg : failed to read KBX', err) - if kbx_userid_tracker not in out: raise_err('gpg : failed to read expected key from KBX') + self.assertEqual(ret, 0, 'gpg : failed to read KBX') + self.assertTrue(kbx_userid_tracker in out, 'gpg : failed to read expected key from KBX') clear_keyrings() def test_generate_protection_pass_fd(self): @@ -1076,195 +1121,204 @@ # Open pipe for password pipe = pswd_pipe(PASSWORD) # Run key generation - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), - '--userid', 'enc@rnp', '--generate-key']) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), + '--userid', KEY_ENC_RNP, '--generate-key']) os.close(pipe) - if ret != 0: - raise_err('key generation failed', err) + self.assertEqual(ret, 0, KEY_GEN_FAILED) # Check packets using the gpg - params = ['--homedir', RNPDIR, '--list-packets', path.join(RNPDIR, 'secring.gpg')] - ret, out, err = run_proc(RNP, params) - match = re.match(RE_RNP_ENCRYPTED_KEY, out) - if not match: - raise_err('wrong encrypted secret key listing', err) + params = ['--homedir', RNPDIR, '--list-packets', os.path.join(RNPDIR, SECRING)] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0) + self.assertRegex(out, RE_RNP_ENCRYPTED_KEY, 'wrong encrypted secret key listing') def test_generate_protection_password(self): ''' Generate key with RNP, using the --password parameter, and make sure key is encrypted ''' clear_keyrings() - params = ['--homedir', RNPDIR, '--password', 'password', '--userid', 'enc@rnp', '--generate-key'] - ret, _, err = run_proc(RNPK, params) - if ret != 0: - raise_err('key generation failed', err) + params = ['--homedir', RNPDIR, '--password', 'password', '--userid', KEY_ENC_RNP, '--generate-key'] + ret, _, _ = run_proc(RNPK, params) + self.assertEqual(ret, 0, KEY_GEN_FAILED) # Check packets using the gpg - params = ['--homedir', RNPDIR, '--list-packets', path.join(RNPDIR, 'secring.gpg')] - ret, out, err = run_proc(RNP, params) - match = re.match(RE_RNP_ENCRYPTED_KEY, out) - if not match: - raise_err('wrong encrypted secret key listing', err) + params = ['--homedir', RNPDIR, '--list-packets', os.path.join(RNPDIR, SECRING)] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0) + self.assertRegex(out, RE_RNP_ENCRYPTED_KEY, 'wrong encrypted secret key listing') def test_generate_unprotected_key(self): ''' Generate key with RNP, using the --password parameter, and make sure key is encrypted ''' clear_keyrings() - params = ['--homedir', RNPDIR, '--password=', '--userid', 'enc@rnp', '--generate-key'] - ret, _, err = run_proc(RNPK, params) - if ret != 0: - raise_err('key generation failed', err) + params = ['--homedir', RNPDIR, '--password=', '--userid', KEY_ENC_RNP, '--generate-key'] + ret, _, _ = run_proc(RNPK, params) + self.assertEqual(ret, 0, KEY_GEN_FAILED) # Check packets using the gpg - params = ['--homedir', RNPDIR, '--list-packets', path.join(RNPDIR, 'secring.gpg')] - ret, out, err = run_proc(RNP, params) - match = re.match(RE_RNP_ENCRYPTED_KEY, out) - if match: - raise_err('wrong unprotected secret key listing', err) + params = ['--homedir', RNPDIR, '--list-packets', os.path.join(RNPDIR, SECRING)] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0) + self.assertNotRegex(out, RE_RNP_ENCRYPTED_KEY, 'wrong unprotected secret key listing') + + def test_generate_preferences(self): + pipe = pswd_pipe(PASSWORD) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', + 'eddsa_25519_prefs', '--generate-key', '--expert'], '22\n') + os.close(pipe) + self.assertEqual(ret, 0) + ret, out, _ = run_proc(RNP, ['--list-packets', os.path.join(RNPDIR, PUBRING)]) + self.assertRegex(out, r'.*preferred symmetric algorithms: AES-256, AES-192, AES-128 \(9, 8, 7\).*') + self.assertRegex(out, r'.*preferred hash algorithms: SHA256, SHA384, SHA512, SHA224 \(8, 9, 10, 11\).*') def test_import_signatures(self): clear_keyrings() + RE_SIG_2_UNCHANGED = r'(?s)^.*Import finished: 0 new signatures, 2 unchanged, 0 unknown.*' # Import command without the path parameter ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs']) - if ret == 0: - raise_err('Sigs import without file failed') - if not re.match(r'(?s)^.*Import file isn\'t specified.*', err): - raise_err('Sigs import without file wrong output') + self.assertNotEqual(ret, 0, 'Sigs import without file failed') + self.assertRegex(err, r'(?s)^.*Import path isn\'t specified.*', 'Sigs import without file wrong output') # Import command with invalid path parameter ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs', data_path('test_key_validity/alice-rev-no-file.pgp')]) - if ret == 0: - raise_err('Sigs import with invalid path failed') - if not re.match(r'(?s)^.*Failed to open file .*', err): - raise_err('Sigs import with invalid path wrong output') + self.assertNotEqual(ret, 0, 'Sigs import with invalid path failed') + self.assertRegex(err, r'(?s)^.*Failed to create input for .*', 'Sigs import with invalid path wrong output') # Try to import signature to empty keyring ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs', data_path('test_key_validity/alice-rev.pgp')]) - if ret != 0: - raise_err('Alice key rev import failed') - if not re.match(r'(?s)^.*Import finished: 0 new signatures, 0 unchanged, 1 unknown.*', err): - raise_err('Alice key rev import wrong output') + self.assertEqual(ret, 0, 'Alice key rev import failed') + self.assertRegex(err, r'(?s)^.*Import finished: 0 new signatures, 0 unchanged, 1 unknown.*', 'Alice key rev import wrong output') # Import Basil's key ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/basil-pub.asc')]) - if ret != 0: - raise_err('Basil key import failed') + self.assertEqual(ret, 0, 'Basil key import failed') # Try to import Alice's signatures with Basil's key only ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sigs.pgp')]) - if ret != 0: - raise_err('Alice sigs import failed') - if not re.match(r'(?s)^.*Import finished: 0 new signatures, 0 unchanged, 2 unknown.*', err): - raise_err('Alice sigs import wrong output') + self.assertEqual(ret, 0, 'Alice sigs import failed') + self.assertRegex(err, r'(?s)^.*Import finished: 0 new signatures, 0 unchanged, 2 unknown.*', 'Alice sigs import wrong output') # Import Alice's key without revocation/direct-key signatures - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-pub.asc')]) - if ret != 0: - raise_err('Alice key import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_ALICE_PUB)]) + self.assertEqual(ret, 0, ALICE_IMPORT_FAIL) # Import key revocation signature ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs', data_path('test_key_validity/alice-rev.pgp')]) - if ret != 0: - raise_err('Alice key rev import failed') - if not re.match(r'(?s)^.*Import finished: 1 new signature, 0 unchanged, 0 unknown.*', err): - raise_err('Alice key rev import wrong output') + self.assertEqual(ret, 0, 'Alice key rev import failed') + self.assertRegex(err, RE_SIG_1_IMPORT, 'Alice key rev import wrong output') # Import direct-key signature ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-revoker-sig.pgp')]) - if ret != 0: - raise_err('Alice direct-key sig import failed') - if not re.match(r'(?s)^.*Import finished: 1 new signature, 0 unchanged, 0 unknown.*', err): - raise_err('Alice direct-key sig import wrong output') + self.assertEqual(ret, 0, 'Alice direct-key sig import failed') + self.assertRegex(err, RE_SIG_1_IMPORT, 'Alice direct-key sig import wrong output') # Try to import two signatures again ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sigs.pgp')]) - if ret != 0: - raise_err('Alice sigs reimport failed') - if not re.match(r'(?s)^.*Import finished: 0 new signatures, 2 unchanged, 0 unknown.*', err): - raise_err('Alice sigs reimport wrong output') + self.assertEqual(ret, 0, 'Alice sigs reimport failed') + self.assertRegex(err, RE_SIG_2_UNCHANGED, 'Alice sigs file reimport wrong output') + # Import two signatures again via stdin + stext = file_text(data_path('test_key_validity/alice-sigs.asc')) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', '-'], stext) + self.assertEqual(ret, 0, 'Alice sigs stdin reimport failed') + self.assertRegex(err, RE_SIG_2_UNCHANGED, 'Alice sigs stdin reimport wrong output') + # Import two signatures via env variable + os.environ["SIG_FILE"] = stext + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', 'env:SIG_FILE']) + self.assertEqual(ret, 0, 'Alice sigs env reimport failed') + self.assertRegex(err, RE_SIG_2_UNCHANGED, 'Alice sigs var reimport wrong output') # Try to import malformed signatures ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sigs-malf.pgp')]) - if ret == 0: - raise_err('Alice malformed sigs import failed') - if not re.match(r'(?s)^.*Failed to import signatures from file .*', err): - raise_err('Alice malformed sigs wrong output') + self.assertNotEqual(ret, 0, 'Alice malformed sigs import failed') + self.assertRegex(err, r'(?s)^.*Failed to import signatures from .*', 'Alice malformed sigs wrong output') def test_export_revocation(self): clear_keyrings() + OUT_NO_REV = 'no-revocation.pgp' + OUT_ALICE_REV = 'alice-revocation.pgp' # Import Alice's public key and be unable to export revocation - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-pub.asc')]) - if ret != 0: - raise_err('Alice key import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_ALICE_PUB)]) + self.assertEqual(ret, 0, ALICE_IMPORT_FAIL) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'alice']) - if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*Revoker secret key not found.*', err): - raise_err('Wrong revocation export output') + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*Revoker secret key not found.*', 'Wrong pubkey revocation export output') # Import Alice's secret key and subkey - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sub-sec.pgp')]) - if ret != 0: - raise_err('Alice secret key import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_ALICE_SUB_SEC)]) + self.assertEqual(ret, 0, 'Alice secret key import failed') # Attempt to export revocation without specifying key pipe = pswd_pipe(PASSWORD) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '--pass-fd', str(pipe)]) os.close(pipe) - if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*You need to specify key to generate revocation for.*', err): - raise_err('Wrong revocation export output', err) + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*You need to specify key to generate revocation for.*', 'Wrong no key revocation export output') # Attempt to export revocation for unknown key ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'basil']) - if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*Key matching \'basil\' not found.*', err): - raise_err('Wrong revocation export output', err) + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*Key matching \'basil\' not found.*', 'Wrong unknown key revocation export output') # Attempt to export revocation for subkey pipe = pswd_pipe(PASSWORD) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'DD23CEB7FEBEFF17']) os.close(pipe) - if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*Key matching \'DD23CEB7FEBEFF17\' not found.*', err): - raise_err('Wrong revocation export output', err) + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*Key matching \'DD23CEB7FEBEFF17\' not found.*', 'Wrong subkey revocation export output') # Attempt to export revocation with too broad search ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/basil-sec.asc')]) - if ret != 0: - raise_err('Basil secret key import failed') + self.assertEqual(ret, 0, 'Basil secret key import failed') pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'rnp', '--pass-fd', str(pipe), - '--output', 'no-revocation.pgp', '--force']) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'rnp', '--pass-fd', str(pipe), + '--output', OUT_NO_REV, '--force']) os.close(pipe) - if (ret == 0) or path.isfile('no-revocation.pgp'): - raise_err('Failed to fail to export revocation') - if not re.match(r'(?s)^.*Ambiguous input: too many keys found for \'rnp\'.*', err): - raise_err('Wrong revocation export output', err) + self.assertNotEqual(ret, 0, 'Failed to fail to export revocation') + self.assertFalse(os.path.isfile(OUT_NO_REV), 'Failed to fail to export revocation') + self.assertRegex(err, r'(?s)^.*Ambiguous input: too many keys found for \'rnp\'.*', 'Wrong revocation export output') # Finally successfully export revocation pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), - '--output', 'alice-revocation.pgp', '--force']) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), + '--output', OUT_ALICE_REV, '--overwrite']) os.close(pipe) - if (ret != 0) or not path.isfile('alice-revocation.pgp'): - raise_err('Failed to export revocation') + self.assertEqual(ret, 0) + self.assertTrue(os.path.isfile(OUT_ALICE_REV)) # Check revocation contents - ret, out, err = run_proc(RNP, ['--homedir', RNPDIR, '--list-packets', 'alice-revocation.pgp']) - if (ret != 0) or (len(out) == 0): - raise_err('Failed to list exported revocation packets') + ret, out, _ = run_proc(RNP, ['--homedir', RNPDIR, '--list-packets', OUT_ALICE_REV]) + self.assertEqual(ret, 0) + self.assertNotEqual(len(out), 0) match = re.match(RE_RNP_REVOCATION_SIG, out) - if not match: - raise_err('Wrong revocation signature contents', out) - if (match.group(1).strip() != '0 (No reason)') or (match.group(2).strip() != ''): - raise_err('Wrong revocation signature contents') + self.assertTrue(match, 'Wrong revocation signature contents') + self.assertEqual(match.group(1).strip(), '0 (No reason)', 'Wrong revocation signature reason') + self.assertEqual(match.group(2).strip(), '', 'Wrong revocation signature message') # Make sure it can be imported back - ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs', 'alice-revocation.pgp']) - if ret != 0: - raise_err('Failed to import revocation back') - if not re.match(r'(?s)^.*Import finished: 1 new signature, 0 unchanged, 0 unknown.*', err): - raise_err('Revocation import wrong output', err) - # Make sure file will not be overwritten without --force parameter - old_size = os.stat('alice-revocation.pgp').st_size + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs', OUT_ALICE_REV]) + self.assertEqual(ret, 0, 'Failed to import revocation back') + self.assertRegex(err, RE_SIG_1_IMPORT, 'Revocation import wrong output') + # Make sure file will not be overwritten with --force parameter + with open(OUT_ALICE_REV, 'w+') as f: + f.truncate(10) pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), '--output', 'alice-revocation.pgp']) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), '--output', OUT_ALICE_REV, '--force', '--notty'], '\n\n') os.close(pipe) - if (ret == 0) or not path.isfile('alice-revocation.pgp') or (old_size != os.stat('alice-revocation.pgp').st_size): - raise_err('Revocation was overwritten without --force parameter') + self.assertNotEqual(ret, 0, 'Revocation was overwritten with --force') + self.assertEqual(10, os.stat(OUT_ALICE_REV).st_size, 'Revocation was overwritten with --force') + # Make sure file will not be overwritten without --overwrite parameter + pipe = pswd_pipe(PASSWORD) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), '--output', OUT_ALICE_REV, '--notty'], '\n\n') + os.close(pipe) + self.assertNotEqual(ret, 0, 'Revocation was overwritten without --overwrite and --force') + self.assertTrue(os.path.isfile(OUT_ALICE_REV), 'Revocation was overwritten without --overwrite') + self.assertEqual(10, os.stat(OUT_ALICE_REV).st_size, 'Revocation was overwritten without --overwrite') + # Make sure file will be overwritten with --overwrite parameter + pipe = pswd_pipe(PASSWORD) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), '--output', OUT_ALICE_REV, '--overwrite']) + os.close(pipe) + self.assertEqual(ret, 0) + self.assertGreater(os.stat(OUT_ALICE_REV).st_size, 10) # Create revocation with wrong code - 'no longer valid' (which is usable only for userid) pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'alice', '--rev-type', 'no longer valid', - '--pass-fd', str(pipe), '--output', 'no-revocation.pgp', '--force']) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'alice', '--rev-type', 'no longer valid', + '--pass-fd', str(pipe), '--output', OUT_NO_REV, '--force']) os.close(pipe) - if (ret == 0) or path.isfile('no-revocation.pgp'): - raise_err('Failed to use wrong revocation reason') - if not re.match(r'(?s)^.*Wrong key revocation code: 32.*', err): - raise_err('Wrong revocation export output', err) + self.assertNotEqual(ret, 0, 'Failed to use wrong revocation reason') + self.assertFalse(os.path.isfile(OUT_NO_REV)) + self.assertRegex(err, r'(?s)^.*Wrong key revocation code: 32.*', 'Wrong revocation export output') # Create revocation without rev-code parameter pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'alice', '--pass-fd', str(pipe), - '--output', 'no-revocation.pgp', '--force', '--rev-type']) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', 'alice', '--pass-fd', str(pipe), + '--output', OUT_NO_REV, '--force', '--rev-type']) os.close(pipe) - if (ret == 0) or path.isfile('no-revocation.pgp'): - raise_err('Failed to use rev-type without parameter') + self.assertNotEqual(ret, 0, 'Failed to use rev-type without parameter') + self.assertFalse(os.path.isfile(OUT_NO_REV), 'Failed to use rev-type without parameter') # Create another revocation with custom code/reason revcodes = {"0" : "0 (No reason)", "1" : "1 (Superseded)", "2" : "2 (Compromised)", "3" : "3 (Retired)", "no" : "0 (No reason)", "superseded" : "1 (Superseded)", @@ -1272,41 +1326,143 @@ for revcode in revcodes: revreason = 'Custom reason: ' + revcode pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), - '--output', 'alice-revocation.pgp', '--force', '--rev-type', revcode, '--rev-reason', revreason]) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-rev', '0451409669FFDE3C', '--pass-fd', str(pipe), + '--output', OUT_ALICE_REV, '--overwrite', '--rev-type', revcode, '--rev-reason', revreason]) os.close(pipe) - if (ret != 0) or not path.isfile('alice-revocation.pgp'): - raise_err('Failed to export revocation with code ' + revcode) + self.assertEqual(ret, 0, 'Failed to export revocation with code ' + revcode) + self.assertTrue(os.path.isfile(OUT_ALICE_REV), 'Failed to export revocation with code ' + revcode) # Check revocation contents - ret, out, err = run_proc(RNP, ['--homedir', RNPDIR, '--list-packets', 'alice-revocation.pgp']) - if (ret != 0) or (len(out) == 0): - raise_err('Failed to list exported revocation packets') + ret, out, _ = run_proc(RNP, ['--homedir', RNPDIR, '--list-packets', OUT_ALICE_REV]) + self.assertEqual(ret, 0, 'Failed to list exported revocation packets') + self.assertNotEqual(len(out), 0, 'Failed to list exported revocation packets') match = re.match(RE_RNP_REVOCATION_SIG, out) - if not match: - raise_err('Wrong revocation signature contents', out) - if (match.group(1).strip() != revcodes[revcode]) or (match.group(2).strip() != revreason ): - raise_err('Wrong revocation signature contents', out) + self.assertTrue(match) + self.assertEqual(match.group(1).strip(), revcodes[revcode], 'Wrong revocation signature revcode') + self.assertEqual(match.group(2).strip(), revreason, 'Wrong revocation signature reason') # Make sure it is also imported back - ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs', 'alice-revocation.pgp']) - if ret != 0: - raise_err('Failed to import revocation back') - if not re.match(r'(?s)^.*Import finished: 1 new signature, 0 unchanged, 0 unknown.*', err): - raise_err('Revocation import wrong output', err) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import-sigs', OUT_ALICE_REV]) + self.assertEqual(ret, 0) + self.assertRegex(err, RE_SIG_1_IMPORT, 'Revocation import wrong output') # Now let's import it with GnuPG - gpg_import_pubring(data_path('test_key_validity/alice-pub.asc')) - ret, _, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', 'alice-revocation.pgp']) - if ret != 0: - raise_err('gpg signature revocation import failed', err) - if not re.match(RE_GPG_REVOCATION_IMPORT, err): - raise_err('Wrong gpg revocation import output') - - os.remove('alice-revocation.pgp') + gpg_import_pubring(data_path(KEY_ALICE_PUB)) + ret, _, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', OUT_ALICE_REV]) + self.assertEqual(ret, 0, 'gpg signature revocation import failed') + self.assertRegex(err, RE_GPG_REVOCATION_IMPORT, 'Wrong gpg revocation import output') + + os.remove(OUT_ALICE_REV) + clear_keyrings() + + def test_export_keys(self): + PUB_KEY = r'(?s)^.*' \ + r'-----BEGIN PGP PUBLIC KEY BLOCK-----.*' \ + r'-----END PGP PUBLIC KEY BLOCK-----.*$' + PUB_KEY_PKTS = r'(?s)^.*' \ + r'Public key packet.*' \ + r'keyid: 0x0451409669ffde3c.*' \ + r'Public subkey packet.*' \ + r'keyid: 0xdd23ceb7febeff17.*$' + SEC_KEY = r'(?s)^.*' \ + r'-----BEGIN PGP PRIVATE KEY BLOCK-----.*' \ + r'-----END PGP PRIVATE KEY BLOCK-----.*$' + SEC_KEY_PKTS = r'(?s)^.*' \ + r'Secret key packet.*' \ + r'keyid: 0x0451409669ffde3c.*' \ + r'Secret subkey packet.*' \ + r'keyid: 0xdd23ceb7febeff17.*$' + KEY_OVERWRITE = r'(?s)^.*' \ + r'File \'.*alice-key.pub.asc\' already exists.*' \ + r'Would you like to overwrite it\? \(y/N\).*' \ + r'Please enter the new filename:.*$' + + clear_keyrings() + # Import Alice's public key + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sub-pub.pgp')]) + self.assertEqual(ret, 0) + # Attempt to export no key + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*No key specified\.$') + # Attempt to export wrong key + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'boris']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Key\(s\) matching \'boris\' not found\.$') + # Export it to the stdout + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice']) + self.assertEqual(ret, 0) + self.assertRegex(out, PUB_KEY) + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', '-']) + self.assertEqual(ret, 0) + self.assertRegex(out, PUB_KEY) + # Export key via --userid parameter + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', '--userid', 'alice']) + self.assertEqual(ret, 0) + self.assertRegex(out, PUB_KEY) + # Export with empty --userid parameter + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', '--userid']) + self.assertNotEqual(ret, 0) + # Export it to the file + kpub, ksec, kren = reg_workfiles('alice-key', '.pub.asc', '.sec.asc', '.pub.ren-asc') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', kpub]) + self.assertEqual(ret, 0) + self.assertRegex(file_text(kpub), PUB_KEY) + # Try to export again to the same file without additional parameters + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', kpub, '--notty'], '\n\n') + self.assertNotEqual(ret, 0) + self.assertRegex(out, KEY_OVERWRITE) + self.assertRegex(err, r'(?s)^.*Operation failed: file \'.*alice-key.pub.asc\' already exists.*$') + # Try to export with --force parameter + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', kpub, '--force', '--notty'], '\n\n') + self.assertNotEqual(ret, 0) + self.assertRegex(out, KEY_OVERWRITE) + self.assertRegex(err, r'(?s)^.*Operation failed: file \'.*alice-key.pub.asc\' already exists.*$') + # Export with --overwrite parameter + with open(kpub, 'w+') as f: + f.truncate(10) + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', kpub, '--overwrite']) + self.assertEqual(ret, 0) + # Re-import it, making sure file was correctly overwriten + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', kpub]) + self.assertEqual(ret, 0) + # Enter 'y' in ovewrite prompt + with open(kpub, 'w+') as f: + f.truncate(10) + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', kpub, '--notty'], 'y\n') + self.assertEqual(ret, 0) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', kpub]) + self.assertEqual(ret, 0) + # Enter new filename in overwrite prompt + with open(kpub, 'w+') as f: + f.truncate(10) + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', kpub, '--notty'], 'n\n' + kren + '\n') + self.assertEqual(ret, 0) + self.assertEqual(os.path.getsize(kpub), 10) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', kren]) + self.assertEqual(ret, 0) + # Attempt to export secret key + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', '--secret', 'alice']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Key\(s\) matching \'alice\' not found\.$') + # Import Alice's secret key and subkey + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_ALICE_SUB_SEC)]) + self.assertEqual(ret, 0) + # Make sure secret key is not exported when public is requested + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', 'alice', '--output', ksec]) + self.assertEqual(ret, 0) + self.assertRegex(file_text(ksec), PUB_KEY) + ret, out, _ = run_proc(RNP, ['--list-packets', ksec]) + self.assertEqual(ret, 0) + self.assertRegex(out, PUB_KEY_PKTS) + # Make sure secret key is correctly exported + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export-key', '--secret', 'alice', '--output', ksec, '--overwrite']) + self.assertEqual(ret, 0) + self.assertRegex(file_text(ksec), SEC_KEY) + ret, out, _ = run_proc(RNP, ['--list-packets', ksec]) + self.assertEqual(ret, 0) + self.assertRegex(out, SEC_KEY_PKTS) clear_keyrings() def test_userid_escape(self): clear_keyrings() - msgs = [] - log = None tracker_beginning = 'tracker' tracker_end = '@rnp' tracker_1 = tracker_beginning + ''.join(map(lambda x : chr(x), range(1,0x10))) + tracker_end @@ -1315,118 +1471,126 @@ rnp_genkey_rsa(tracker_1, 1024) rnp_genkey_rsa(tracker_2, 1024) #Read with rnpkeys - ret, out_rnp, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if ret != 0: - msgs.append('rnpkeys : failed to read keystore') - log = err + ret, out_rnp, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0, 'rnpkeys : failed to read keystore') #Read with GPG - ret, out_gpg, err = run_proc(GPG, ['--homedir', path_for_gpg(RNPDIR), '--list-keys']) - if ret != 0: - msgs.append('gpg : failed to read keystore') - log = err - if msgs: - raise_err('\n'.join(msgs), log) + ret, out_gpg, _ = run_proc(GPG, ['--homedir', path_for_gpg(RNPDIR), '--list-keys']) + self.assertEqual(ret, 0, 'gpg : failed to read keystore') tracker_rnp = re.findall(r'' + tracker_beginning + '.*' + tracker_end + '', out_rnp) tracker_gpg = re.findall(r'' + tracker_beginning + '.*' + tracker_end + '', out_gpg) - if len(tracker_rnp) != 2 or len(tracker_gpg) != 2: - raise_err('failed to find expected userids') - if tracker_rnp != tracker_gpg: - raise_err('userids from rnpkeys and gpg don\'t match') + self.assertEqual(len(tracker_rnp), 2, 'failed to find expected rnp userids') + self.assertEqual(len(tracker_gpg), 2, 'failed to find expected gpg userids') + self.assertEqual(tracker_rnp, tracker_gpg, 'userids from rnpkeys and gpg don\'t match') clear_keyrings() def test_key_revoke(self): clear_keyrings() # Import Alice's public key and be unable to revoke - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-pub.asc')]) - if ret != 0: - raise_err('Alice key import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_ALICE_PUB)]) + self.assertEqual(ret, 0, ALICE_IMPORT_FAIL) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke-key', 'alice']) - if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*Revoker secret key not found.*Failed to revoke a key.*', err): - raise_err('Wrong revocation output') + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*Revoker secret key not found.*Failed to revoke a key.*') # Import Alice's secret key and subkey - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sub-sec.pgp')]) - if ret != 0: - raise_err('Alice secret key import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_ALICE_SUB_SEC)]) + self.assertEqual(ret, 0) # Attempt to revoke without specifying a key pipe = pswd_pipe(PASSWORD) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '--pass-fd', str(pipe)]) os.close(pipe) - if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*You need to specify key or subkey to revoke.*', err): - raise_err('Wrong revocation output', err) + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*You need to specify key or subkey to revoke.*') # Attempt to revoke unknown key ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'basil']) - if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*Key matching \'basil\' not found.*', err): - raise_err('Wrong revocation output', err) + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*Key matching \'basil\' not found.*') # Attempt to revoke with too broad search ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/basil-sec.asc')]) - if ret != 0: - raise_err('Basil secret key import failed') + self.assertEqual(ret, 0) pipe = pswd_pipe(PASSWORD) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'rnp', '--pass-fd', str(pipe)]) os.close(pipe) - if not re.match(r'(?s)^.*Ambiguous input: too many keys found for \'rnp\'.*', err): - raise_err('Wrong revocation export output', err) + self.assertRegex(err, r'(?s)^.*Ambiguous input: too many keys found for \'rnp\'.*') # Revoke a primary key pipe = pswd_pipe(PASSWORD) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '0451409669FFDE3C', '--pass-fd', str(pipe)]) os.close(pipe) - if (ret != 0): - raise_err('Failed to revoke alice key') + self.assertEqual(ret, 0) ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if (ret != 0) or not re.match(r'(?s)^.*pub.*0451409669ffde3c.*\[REVOKED\].*73edcc9119afc8e2dbbdcde50451409669ffde3c.*', out): - raise_err('Wrong revoked key listing', out) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*pub.*0451409669ffde3c.*\[REVOKED\].*73edcc9119afc8e2dbbdcde50451409669ffde3c.*') # Try again without the '--force' parameter pipe = pswd_pipe(PASSWORD) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '0451409669FFDE3C', '--pass-fd', str(pipe)]) os.close(pipe) - if (ret == 0): - raise_err('Failed to fail to revoke alice key') - if (len(out) > 0) or not re.match(r'(?s)^.*Error: key \'0451409669FFDE3C\' is revoked already. Use --force to generate another revocation signature.*', err): - raise_err('Wrong revocation output', err) + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*Error: key \'0451409669FFDE3C\' is revoked already. Use --force to generate another revocation signature.*') # Try again with --force parameter pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '0451409669FFDE3C', '--pass-fd', str(pipe), "--force", "--rev-type", "3", "--rev-reason", "Custom"]) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '0451409669FFDE3C', '--pass-fd', str(pipe), "--force", "--rev-type", "3", "--rev-reason", "Custom"]) os.close(pipe) - if (ret != 0): - raise_err('Failed to revoke alice key') + self.assertEqual(ret, 0) ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if (ret != 0) or not re.match(r'(?s)^.*pub.*0451409669ffde3c.*\[REVOKED\].*73edcc9119afc8e2dbbdcde50451409669ffde3c.*', out): - raise_err('Wrong revoked key listing', out) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*pub.*0451409669ffde3c.*\[REVOKED\].*73edcc9119afc8e2dbbdcde50451409669ffde3c.*') # Revoke a subkey pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe)]) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe)]) os.close(pipe) - if (ret != 0): - raise_err('Failed to revoke alice subkey') + self.assertEqual(ret, 0) ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if (ret != 0) or not re.match(r'(?s)^.*sub.*dd23ceb7febeff17.*\[REVOKED\].*a4bbb77370217bca2307ad0ddd23ceb7febeff17.*', out): - raise_err('Wrong revoked subkey listing', out) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*sub.*dd23ceb7febeff17.*\[REVOKED\].*a4bbb77370217bca2307ad0ddd23ceb7febeff17.*') # Try again without the '--force' parameter pipe = pswd_pipe(PASSWORD) ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe)]) os.close(pipe) - if (ret == 0): - raise_err('Failed to fail to revoke alice subkey') - if (len(out) > 0) or not re.match(r'(?s)^.*Error: key \'DD23CEB7FEBEFF17\' is revoked already. Use --force to generate another revocation signature.*', err): - raise_err('Wrong revocation output', err) + self.assertNotEqual(ret, 0) + self.assertEqual(len(out), 0) + self.assertRegex(err, r'(?s)^.*Error: key \'DD23CEB7FEBEFF17\' is revoked already. Use --force to generate another revocation signature.*', err) # Try again with --force parameter pipe = pswd_pipe(PASSWORD) - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe), "--force", "--rev-type", "2", "--rev-reason", "Other"]) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe), "--force", "--rev-type", "2", "--rev-reason", "Other"]) os.close(pipe) - if (ret != 0): - raise_err('Failed to revoke alice subkey') + self.assertEqual(ret, 0) ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if (ret != 0) or not re.match(r'(?s)^.*sub.*dd23ceb7febeff17.*\[REVOKED\].*a4bbb77370217bca2307ad0ddd23ceb7febeff17.*', out): - raise_err('Wrong revoked subkey listing', out) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*sub.*dd23ceb7febeff17.*\[REVOKED\].*a4bbb77370217bca2307ad0ddd23ceb7febeff17.*') + + def _test_userid_genkey(self, userid_beginning, weird_part, userid_end, weird_part2=''): + clear_keyrings() + USERS = [userid_beginning + weird_part + userid_end] + if weird_part2: + USERS.append(userid_beginning + weird_part2 + userid_end) + # Run key generation + for userid in USERS: + rnp_genkey_rsa(userid, 1024) + # Read with GPG + ret, out, err = run_proc(GPG, ['--homedir', path_for_gpg(RNPDIR), '--list-keys', '--charset', CONSOLE_ENCODING]) + self.assertEqual(ret, 0, 'gpg : failed to read keystore') + tracker_escaped = re.findall(r'' + userid_beginning + '.*' + userid_end + '', out) + tracker_gpg = list(map(decode_string_escape, tracker_escaped)) + self.assertEqual(tracker_gpg, USERS, 'gpg : failed to find expected userids from keystore') + # Read with rnpkeys + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0, 'rnpkeys : failed to read keystore') + tracker_escaped = re.findall(r'' + userid_beginning + '.*' + userid_end + '', out) + tracker_rnp = list(map(decode_string_escape, tracker_escaped)) + self.assertEqual(tracker_rnp, USERS, 'rnpkeys : failed to find expected userids from keystore') + clear_keyrings() def test_userid_unicode_genkeys(self): - test_userid_genkey('track', WEIRD_USERID_UNICODE_1, 'end', WEIRD_USERID_UNICODE_2) + self._test_userid_genkey('track', WEIRD_USERID_UNICODE_1, 'end', WEIRD_USERID_UNICODE_2) def test_userid_special_chars_genkeys(self): - test_userid_genkey('track', WEIRD_USERID_SPECIAL_CHARS, 'end') - test_userid_genkey('track', WEIRD_USERID_SPACE, 'end') - test_userid_genkey('track', WEIRD_USERID_QUOTE, 'end') - test_userid_genkey('track', WEIRD_USERID_SPACE_AND_QUOTE, 'end') + self._test_userid_genkey('track', WEIRD_USERID_SPECIAL_CHARS, 'end') + self._test_userid_genkey('track', WEIRD_USERID_SPACE, 'end') + self._test_userid_genkey('track', WEIRD_USERID_QUOTE, 'end') + self._test_userid_genkey('track', WEIRD_USERID_SPACE_AND_QUOTE, 'end') def test_userid_too_long_genkeys(self): clear_keyrings() @@ -1434,78 +1598,73 @@ # Open pipe for password pipe = pswd_pipe(PASSWORD) # Run key generation - ret, out, err = run_proc(RNPK, ['--gen-key', '--userid', userid, - '--homedir', RNPDIR, '--pass-fd', str(pipe)]) + ret, _, _ = run_proc(RNPK, ['--gen-key', '--userid', userid, + '--homedir', RNPDIR, '--pass-fd', str(pipe)]) os.close(pipe) - if ret == 0: raise_err('should have failed on too long id', err) + self.assertNotEqual(ret, 0, 'should have failed on too long id') def test_key_remove(self): + MSG_KEYS_NOT_FOUND = r'Key\(s\) not found\.' clear_keyrings() # Import public keyring - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('keyrings/1/pubring.gpg')]) - if ret != 0: - raise_err('Public keyring import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(PUBRING_1)]) + self.assertEqual(ret, 0) + # Remove without parameters + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key']) + self.assertNotEqual(ret, 0) # Remove all imported public keys with subkeys - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a', '2fcadf05ffa501bb']) - if (ret != 0): - raise_err('Failed to remove keys', err) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a', '2fcadf05ffa501bb']) + self.assertEqual(ret, 0) # Check that keyring is empty ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if not re.match(r'Key\(s\) not found\.', out): - raise_err('Failed to remove public keys'); + self.assertNotEqual(ret, 0) + self.assertRegex(out, MSG_KEYS_NOT_FOUND, 'Invalid no-keys output') # Import secret keyring ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('keyrings/1/secring.gpg')]) - if ret != 0: - raise_err('Secret keyring import failed') + self.assertEqual(ret, 0, 'Secret keyring import failed') # Remove all secret keys with subkeys - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a', '2fcadf05ffa501bb', '--force']) - if (ret != 0): - raise_err('Failed to remove keys', err) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a', '2fcadf05ffa501bb', '--force']) + self.assertEqual(ret, 0, 'Failed to remove 2 secret keys') # Check that keyring is empty ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if not re.match(r'Key\(s\) not found\.', out): - raise_err('Failed to remove secret keys'); + self.assertNotEqual(ret, 0) + self.assertRegex(out, MSG_KEYS_NOT_FOUND, 'Failed to remove secret keys') # Import public keyring - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('keyrings/1/pubring.gpg')]) - if ret != 0: - raise_err('Public keyring import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(PUBRING_1)]) + self.assertEqual(ret, 0, 'Public keyring import failed') # Remove all subkeys ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '326ef111425d14a5', '54505a936a4a970e', '8a05b89fad5aded1', '1d7e8a5393c997a8', '1ed63ee56fadc34d']) - if (ret != 0): - raise_err('Failed to remove keys', err) + self.assertEqual(ret, 0, 'Failed to remove 5 keys') # Check that subkeys are removed ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if (ret != 0) or not re.match(r'2 keys found', out) or re.search('326ef111425d14a5|54505a936a4a970e|8a05b89fad5aded1|1d7e8a5393c997a8|1ed63ee56fadc34d', out): - raise_err('Failed to remove subkeys'); + self.assertEqual(ret, 0) + self.assertRegex(out, r'2 keys found', 'Failed to remove subkeys') + self.assertFalse(re.search('326ef111425d14a5|54505a936a4a970e|8a05b89fad5aded1|1d7e8a5393c997a8|1ed63ee56fadc34d', out)) # Remove remaining public keys - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a', '2fcadf05ffa501bb']) - if (ret != 0): - raise_err('Failed to remove keys', err) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a', '2fcadf05ffa501bb']) + self.assertEqual(ret, 0, 'Failed to remove public keys') # Try to remove again - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a']) - if (ret == 0) or not re.search(r'Key matching \'7bc6709b15c23a4a\' not found\.', err): - raise_err('Unexpected result', err) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '7bc6709b15c23a4a']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'Key matching \'7bc6709b15c23a4a\' not found\.', 'Unexpected result') # Check that keyring is empty ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if not re.match(r'Key\(s\) not found\.', out): - raise_err('Failed to remove keys'); + self.assertRegex(out, MSG_KEYS_NOT_FOUND, 'Failed to list empty keyring') # Import public keyring - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('keyrings/1/pubring.gpg')]) - if ret != 0: - raise_err('Public keyring import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(PUBRING_1)]) + self.assertEqual(ret, 0, 'Public keyring import failed') # Try to remove by uid substring, should match multiple keys and refuse to remove - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', 'uid0']) - if (ret == 0) or not re.search(r'Ambiguous input: too many keys found for \'uid0\'\.', err): - raise_err('Unexpected result', err) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', 'uid0']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'Ambiguous input: too many keys found for \'uid0\'\.', 'Unexpected result') # Remove keys by uids - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', 'key0-uid0', 'key1-uid1']) - if (ret != 0): - raise_err('Failed to remove keys', err) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', 'key0-uid0', 'key1-uid1']) + self.assertEqual(ret, 0, 'Failed to remove keys') # Check that keyring is empty ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) - if not re.match(r'Key\(s\) not found\.', out): - raise_err('Failed to remove keys'); + self.assertNotEqual(ret, 0) + self.assertRegex(out, MSG_KEYS_NOT_FOUND, 'Failed to remove keys') class Misc(unittest.TestCase): @@ -1535,7 +1694,7 @@ rnp_encrypt_file_ex(src, dst, [KEY_ENCRYPT]) rnp_decrypt_file(dst, dec) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) remove_files(src, dst, dec) @@ -1547,22 +1706,24 @@ params = ['--homedir', GPGHOME, '-c', '-z', '0', '--disable-mdc', '--s2k-count', '65536', '--batch', '--passphrase', PASSWORD, '--output', path_for_gpg(dst), path_for_gpg(src)] - ret, _, err = run_proc(GPG, params) - if ret != 0: - raise_err('gpg symmetric encryption failed', err) + ret, _, _ = run_proc(GPG, params) + self.assertEqual(ret, 0, 'gpg symmetric encryption failed') # Decrypt encrypted file with RNP rnp_decrypt_file(dst, dec) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) def test_encryption_s2k(self): src, dst, dec = reg_workfiles('cleartext', '.txt', '.gpg', '.rnp') - random_text(src, 64000) + random_text(src, 1000) ciphers = ['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256', 'IDEA', '3DES', 'CAST5', 'BLOWFISH'] hashes = ['SHA1', 'RIPEMD160', 'SHA256', 'SHA384', 'SHA512', 'SHA224'] s2kmodes = [0, 1, 3] + if not RNP_TWOFISH: + ciphers.remove('TWOFISH') + def rnp_encryption_s2k_gpg(cipher, hash_alg, s2k=None, iterations=None): params = ['--homedir', GPGHOME, '-c', '--s2k-cipher-algo', cipher, '--s2k-digest-algo', hash_alg, '--batch', '--passphrase', PASSWORD, @@ -1576,14 +1737,16 @@ params.insert(9, '--s2k-count') params.insert(10, str(iterations)) - ret, _, err = run_proc(GPG, params) - if ret != 0: - raise_err('gpg symmetric encryption failed', err) + if GPG_NO_OLD: + params.insert(3, '--allow-old-cipher-algos') + + ret, _, _ = run_proc(GPG, params) + self.assertEqual(ret, 0, 'gpg symmetric encryption failed') rnp_decrypt_file(dst, dec) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) remove_files(dst, dec) - for i in range(0, 80): + for i in range(0, 20): rnp_encryption_s2k_gpg(ciphers[i % len(ciphers)], hashes[ i % len(hashes)], s2kmodes[i % len(s2kmodes)]) @@ -1593,92 +1756,117 @@ armor_types = [('msg', 'MESSAGE'), ('pubkey', 'PUBLIC KEY BLOCK'), ('seckey', 'PRIVATE KEY BLOCK'), ('sign', 'SIGNATURE')] + # Wrong armor type + ret, _, err = run_proc(RNP, ['--enarmor', 'wrong', src_beg, '--output', dst_beg]) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Wrong enarmor argument: wrong.*$') + for data_type, header in armor_types: random_text(src_beg, 1000) prefix = '-----BEGIN PGP ' + header + '-----' suffix = '-----END PGP ' + header + '-----' - run_proc(RNP, ['--enarmor', data_type, src_beg, '--output', dst_beg]) + ret, _, _ = run_proc(RNP, ['--enarmor', data_type, src_beg, '--output', dst_beg]) + self.assertEqual(ret, 0) txt = file_text(dst_beg).strip('\r\n') - if not (txt.startswith(prefix) and txt.endswith(suffix)): - raise_err('wrong armor header or trailer', txt) + self.assertTrue(txt.startswith(prefix), 'wrong armor header') + self.assertTrue(txt.endswith(suffix), 'wrong armor trailer') - run_proc(RNP, ['--dearmor', dst_beg, '--output', dst_mid]) - run_proc(RNP, ['--enarmor', data_type, dst_mid, '--output', dst_fin]) + ret, _, _ = run_proc(RNP, ['--dearmor', dst_beg, '--output', dst_mid]) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(RNP, ['--enarmor', data_type, dst_mid, '--output', dst_fin]) + self.assertEqual(ret, 0) compare_files(dst_beg, dst_fin, "RNP armor/dearmor test failed") compare_files(src_beg, dst_mid, "RNP armor/dearmor test failed") remove_files(dst_beg, dst_mid, dst_fin) def test_rnpkeys_lists(self): + KEYRING_1 = data_path('keyrings/1') + KEYRING_2 = data_path('keyrings/2') + KEYRING_3 = data_path('keyrings/3') + KEYRING_5 = data_path('keyrings/5') path = data_path('test_cli_rnpkeys') + '/' - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '--list-keys']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_1, '--list-keys']) compare_file_any(allow_y2k38_on_32bit(path + 'keyring_1_list_keys'), out, 'keyring 1 key listing failed') - _, out, _ = run_proc(RNPK, ['--hom', data_path('keyrings/1'), '-l', '--with-sigs']) + _, out, _ = run_proc(RNPK, ['--hom', KEYRING_1, '-l', '--with-sigs']) compare_file_any(allow_y2k38_on_32bit(path + 'keyring_1_list_sigs'), out, 'keyring 1 sig listing failed') - _, out, _ = run_proc(RNPK, ['--home', data_path('keyrings/1'), '--list-keys', '--secret']) + _, out, _ = run_proc(RNPK, ['--home', KEYRING_1, '--list-keys', '--secret']) compare_file_any(allow_y2k38_on_32bit(path + 'keyring_1_list_keys_sec'), out, 'keyring 1 sec key listing failed') - _, out, _ = run_proc(RNPK, ['--home', data_path('keyrings/1'), '--list-keys', + _, out, _ = run_proc(RNPK, ['--home', KEYRING_1, '--list-keys', '--secret', '--with-sigs']) compare_file_any(allow_y2k38_on_32bit(path + 'keyring_1_list_sigs_sec'), out, 'keyring 1 sec sig listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/2'), '--list-keys']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_2, '--list-keys']) compare_file(path + 'keyring_2_list_keys', out, 'keyring 2 key listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/2'), '-l', '--with-sigs']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_2, '-l', '--with-sigs']) compare_file(path + 'keyring_2_list_sigs', out, 'keyring 2 sig listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/3'), '--list-keys']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_3, '--list-keys']) compare_file_any(allow_y2k38_on_32bit(path + 'keyring_3_list_keys'), out, 'keyring 3 key listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/3'), '-l', '--with-sigs']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_3, '-l', '--with-sigs']) compare_file_any(allow_y2k38_on_32bit(path + 'keyring_3_list_sigs'), out, 'keyring 3 sig listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/5'), '--list-keys']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_5, '--list-keys']) compare_file(path + 'keyring_5_list_keys', out, 'keyring 5 key listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/5'), '-l', '--with-sigs']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_5, '-l', '--with-sigs']) compare_file(path + 'keyring_5_list_sigs', out, 'keyring 5 sig listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), + _, out, _ = run_proc(RNPK, ['--homedir', data_path(SECRING_G10), '--list-keys']) - compare_file(path + 'test_stream_key_load_keys', out, 'g10 keyring key listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), + if RNP_BRAINPOOL: + self.assertEqual(file_text(path + 'test_stream_key_load_keys'), out, 'g10 keyring key listing failed') + else: + self.assertEqual(file_text(path + 'test_stream_key_load_keys_no_bp'), out, 'g10 keyring key listing failed') + _, out, _ = run_proc(RNPK, ['--homedir', data_path(SECRING_G10), '-l', '--with-sigs']) - compare_file(path + 'test_stream_key_load_sigs', out, 'g10 keyring sig listing failed') + if RNP_BRAINPOOL: + self.assertEqual(file_text(path + 'test_stream_key_load_sigs'), out, 'g10 keyring sig listing failed') + else: + self.assertEqual(file_text(path + 'test_stream_key_load_sigs_no_bp'), out, 'g10 keyring sig listing failed') # Below are disabled until we have some kind of sorting which doesn't depend on # readdir order - #_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), + #_, out, _ = run_proc(RNPK, ['--homedir', data_path(SECRING_G10), # '-l', '--secret']) #compare_file(path + 'test_stream_key_load_keys_sec', out, # 'g10 sec keyring key listing failed') - #_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), + #_, out, _ = run_proc(RNPK, ['--homedir', data_path(SECRING_G10), # '-l', '--secret', '--with-sigs']) #compare_file(path + 'test_stream_key_load_sigs_sec', out, # 'g10 sec keyring sig listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', '2fcadf05ffa501bb']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_1, '-l', '2fcadf05ffa501bb']) compare_file_any(allow_y2k38_on_32bit(path + 'getkey_2fcadf05ffa501bb'), out, 'list key 2fcadf05ffa501bb failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_1, '-l', '--with-sigs', '2fcadf05ffa501bb']) compare_file_any(allow_y2k38_on_32bit(path + 'getkey_2fcadf05ffa501bb_sig'), out, 'list sig 2fcadf05ffa501bb failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_1, '-l', '--secret', '2fcadf05ffa501bb']) compare_file_any(allow_y2k38_on_32bit(path + 'getkey_2fcadf05ffa501bb_sec'), out, 'list sec 2fcadf05ffa501bb failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', '00000000']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_1, '-l', '00000000']) compare_file(path + 'getkey_00000000', out, 'list key 00000000 failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', 'zzzzzzzz']) + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_1, '-l', 'zzzzzzzz']) compare_file(path + 'getkey_zzzzzzzz', out, 'list key zzzzzzzz failed') + _, out, _ = run_proc(RNPK, ['--homedir', KEYRING_1, '-l', '--userid', '2fcadf05ffa501bb']) + compare_file_any(allow_y2k38_on_32bit(path + 'getkey_2fcadf05ffa501bb'), out, 'list key 2fcadf05ffa501bb failed') + def test_rnpkeys_g10_list_order(self): - _, out, _ = run_proc(RNPK, ['--homedir', data_path( - 'test_stream_key_load/g10'), '--list-keys']) - compare_file(data_path('test_cli_rnpkeys/g10_list_keys'), out, 'g10 key listing failed') - _, out, _ = run_proc(RNPK, ['--homedir', data_path( - 'test_stream_key_load/g10'), '--secret', '--list-keys']) - compare_file(data_path('test_cli_rnpkeys/g10_list_keys_sec'), out, - 'g10 secret key listing failed') - return + ret, out, _ = run_proc(RNPK, ['--homedir', data_path(SECRING_G10), '--list-keys']) + self.assertEqual(ret, 0) + if RNP_BRAINPOOL: + self.assertEqual(file_text(data_path('test_cli_rnpkeys/g10_list_keys')), out, 'g10 key listing failed') + else: + self.assertEqual(file_text(data_path('test_cli_rnpkeys/g10_list_keys_no_bp')), out, 'g10 key listing failed') + ret, out, _ = run_proc(RNPK, ['--homedir', data_path(SECRING_G10), '--secret', '--list-keys']) + self.assertEqual(ret, 0) + if RNP_BRAINPOOL: + self.assertEqual(file_text(data_path('test_cli_rnpkeys/g10_list_keys_sec')), out, 'g10 secret key listing failed') + else: + self.assertEqual(file_text(data_path('test_cli_rnpkeys/g10_list_keys_sec_no_bp')), out, 'g10 secret key listing failed') def test_rnpkeys_g10_def_key(self): RE_SIG = r'(?s)^.*' \ @@ -1695,303 +1883,727 @@ params = ['--homedir', data_path('test_cli_g10_defkey/g10'), '--password', PASSWORD, '--output', dst, '-s', src] ret, _, err = run_proc(RNP, params) - if ret != 0: - raise_err('rnp signing failed', err) + self.assertEqual(ret, 0, 'rnp signing failed') # Verify signed file params = ['--homedir', data_path('test_cli_g10_defkey/g10'), '-v', dst] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('verification failed', err) - match = re.match(RE_SIG, err) - if not match: - raise_err('wrong rnp g10 verification output', err) - return + ret, _, err = run_proc(RNP, params) + self.assertEqual(ret, 0, 'verification failed') + self.assertRegex(err, RE_SIG, 'wrong rnp g10 verification output') def test_large_packet(self): # Verifying large packet file with GnuPG - kpath = path_for_gpg(data_path('keyrings/1/pubring.gpg')) + kpath = path_for_gpg(data_path(PUBRING_1)) dpath = path_for_gpg(data_path('test_large_packet/4g.bzip2.gpg')) - ret, _, err = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', dpath]) - if ret != 0: - raise_err('large packet verification failed', err) - return + ret, _, _ = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', dpath]) + self.assertEqual(ret, 0, 'large packet verification failed') def test_partial_length_signature(self): # Verifying partial length signature with GnuPG - kpath = path_for_gpg(data_path('keyrings/1/pubring.gpg')) + kpath = path_for_gpg(data_path(PUBRING_1)) mpath = path_for_gpg(data_path('test_partial_length/message.txt.partial-signed')) ret, _, _ = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', mpath]) - if ret == 0: - raise_err('partial length signature packet should result in failure but did not') - return + self.assertNotEqual(ret, 0, 'partial length signature packet should result in failure but did not') def test_partial_length_public_key(self): # Reading keyring that has a public key packet with partial length using GnuPG kpath = data_path('test_partial_length/pubring.gpg.partial') ret, _, _ = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--list-keys']) - if ret == 0: - raise_err('partial length public key packet should result in failure but did not') - return + self.assertNotEqual(ret, 0, 'partial length public key packet should result in failure but did not') def test_partial_length_zero_last_chunk(self): # Verifying message in partial packets having 0-size last chunk with GnuPG - kpath = path_for_gpg(data_path('keyrings/1/pubring.gpg')) + kpath = path_for_gpg(data_path(PUBRING_1)) mpath = path_for_gpg(data_path('test_partial_length/message.txt.partial-zero-last')) - ret, _, err = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', mpath]) - if ret != 0: - raise_err('message in partial packets having 0-size last chunk ' \ - 'verification failed', err) - return + ret, _, _ = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', mpath]) + self.assertEqual(ret, 0, 'message in partial packets having 0-size last chunk verification failed') def test_partial_length_largest(self): # Verifying message having largest possible partial packet with GnuPG - kpath = path_for_gpg(data_path('keyrings/1/pubring.gpg')) + kpath = path_for_gpg(data_path(PUBRING_1)) mpath = path_for_gpg(data_path('test_partial_length/message.txt.partial-1g')) - ret, _, err = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', mpath]) - if ret != 0: - raise_err('message having largest possible partial packet verification failed', err) - return + ret, _, _ = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', mpath]) + self.assertEqual(ret, 0, 'message having largest possible partial packet verification failed') def test_rnp_single_export(self): # Import key with subkeys, then export it, test that it is exported once. # See issue #1153 clear_keyrings() # Import Alice's secret key and subkey - ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sub-sec.pgp')]) - if ret != 0: - raise_err('Alice secret key import failed') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_ALICE_SUB_SEC)]) + self.assertEqual(ret, 0, 'Alice secret key import failed') # Export key - ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--export', 'Alice']) - if ret != 0: raise_err('key export failed', err) - pubpath = path.join(RNPDIR, 'Alice-export-test.asc') + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export', 'Alice']) + self.assertEqual(ret, 0, 'key export failed') + pubpath = os.path.join(RNPDIR, 'Alice-export-test.asc') with open(pubpath, 'w+') as f: f.write(out) # List exported key packets params = ['--list-packets', pubpath] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_single_export_subkeys/list_key_export_single.txt'), out, 'exported packets mismatch') - return def test_rnp_permissive_key_import(self): # Import keys while skipping bad packets, see #1160 clear_keyrings() # Try to import without --permissive option, should fail. ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import-keys', data_path('test_key_edge_cases/pubring-malf-cert.pgp')]) - if ret == 0: - raise_err('Imported bad packets without --permissive option set!') + self.assertNotEqual(ret, 0, 'Imported bad packets without --permissive option set!') # Import with --permissive ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import-keys', '--permissive',data_path('test_key_edge_cases/pubring-malf-cert.pgp')]) - if ret != 0: - raise_err('Failed to import keys with --permissive option') + self.assertEqual(ret, 0, 'Failed to import keys with --permissive option') # List imported keys and sigs params = ['--homedir', RNPDIR, '--list-keys', '--with-sigs'] - ret, out, err = run_proc(RNPK, params) - if ret != 0: - raise_err('packet listing failed', err) + ret, out, _ = run_proc(RNPK, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_any(allow_y2k38_on_32bit(data_path('test_cli_rnpkeys/pubring-malf-cert-permissive-import.txt')), out, 'listing mismatch') - return def test_rnp_list_packets(self): + KEY_P256 = data_path('test_list_packets/ecc-p256-pub.asc') # List packets in humand-readable format - params = ['--list-packets', data_path('test_list_packets/ecc-p256-pub.asc')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + params = ['--list-packets', KEY_P256] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_list_packets/list_standard.txt'), out, 'standard listing mismatch') # List packets with mpi values - params = ['--mpi', '--list-packets', data_path('test_list_packets/ecc-p256-pub.asc')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing with mpi failed', err) + params = ['--mpi', '--list-packets', KEY_P256] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'packet listing with mpi failed') compare_file_ex(data_path('test_list_packets/list_mpi.txt'), out, 'mpi listing mismatch') # List packets with grip/fingerprint values - params = ['--list-packets', data_path('test_list_packets/ecc-p256-pub.asc'), '--grips'] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing with grips failed', err) + params = ['--list-packets', KEY_P256, '--grips'] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'packet listing with grips failed') compare_file_ex(data_path('test_list_packets/list_grips.txt'), out, 'grips listing mismatch') # List packets with raw packet contents - params = ['--list-packets', data_path('test_list_packets/ecc-p256-pub.asc'), '--raw'] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing with raw packets failed', err) + params = ['--list-packets', KEY_P256, '--raw'] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'packet listing with raw packets failed') compare_file_ex(data_path('test_list_packets/list_raw.txt'), out, 'raw listing mismatch') # List packets with all options enabled - params = ['--list-packets', data_path('test_list_packets/ecc-p256-pub.asc'), - '--grips', '--raw', '--mpi'] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing with all options failed', err) + params = ['--list-packets', KEY_P256, '--grips', '--raw', '--mpi'] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'packet listing with all options failed') compare_file_ex(data_path('test_list_packets/list_all.txt'), out, 'all listing mismatch') # List packets with JSON output - params = ['--json', '--list-packets', data_path('test_list_packets/ecc-p256-pub.asc')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('json packet listing failed', err) + params = ['--json', '--list-packets', KEY_P256] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'json packet listing failed') compare_file_ex(data_path('test_list_packets/list_json.txt'), out, 'json listing mismatch') # List packets with mpi values, JSON output - params = ['--json', '--mpi', '--list-packets', data_path( - 'test_list_packets/ecc-p256-pub.asc')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('json mpi packet listing failed', err) + params = ['--json', '--mpi', '--list-packets', KEY_P256] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'json mpi packet listing failed') compare_file_ex(data_path('test_list_packets/list_json_mpi.txt'), out, 'json mpi listing mismatch') # List packets with grip/fingerprint values, JSON output - params = ['--json', '--grips', '--list-packets', data_path( - 'test_list_packets/ecc-p256-pub.asc')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('json grips packet listing failed', err) + params = ['--json', '--grips', '--list-packets', KEY_P256] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'json grips packet listing failed') compare_file_ex(data_path('test_list_packets/list_json_grips.txt'), out, 'json grips listing mismatch') # List packets with raw packet values, JSON output - params = ['--json', '--raw', '--list-packets', data_path( - 'test_list_packets/ecc-p256-pub.asc')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('json raw packet listing failed', err) + params = ['--json', '--raw', '--list-packets', KEY_P256] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'json raw packet listing failed') compare_file_ex(data_path('test_list_packets/list_json_raw.txt'), out, 'json raw listing mismatch') # List packets with all values, JSON output - params = ['--json', '--raw', '--list-packets', data_path( - 'test_list_packets/ecc-p256-pub.asc'), '--mpi', '--grips'] + params = ['--json', '--raw', '--list-packets', KEY_P256, '--mpi', '--grips'] ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('json all listing failed', err) + self.assertEqual(ret, 0, 'json all listing failed') compare_file_ex(data_path('test_list_packets/list_json_all.txt'), out, 'json all listing mismatch') - return + # List packets with notations + params = ['--list-packets', data_path('test_key_edge_cases/key-critical-notations.pgp')] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*notation data: critical text = critical value.*$') + self.assertRegex(out, r'(?s)^.*notation data: critical binary = 0x000102030405060708090a0b0c0d0e0f \(16 bytes\).*$') + # List packets with notations via JSON + params = ['--list-packets', '--json', data_path('test_key_edge_cases/key-critical-notations.pgp')] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*\"human\":true.*\"name\":\"critical text\".*\"value\":\"critical value\".*$') + self.assertRegex(out, r'(?s)^.*\"human\":false.*\"name\":\"critical binary\".*\"value\":\"000102030405060708090a0b0c0d0e0f\".*$') + # List test file with critical notation + params = ['--list-packets', data_path('test_messages/message.txt.signed.crit-notation')] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*:type 20, len 35, critical.*notation data: critical text = critical value.*$') def test_rnp_list_packets_edge_cases(self): + KEY_EMPTY_UID = data_path('test_key_edge_cases/key-empty-uid.pgp') # List empty key packets params = ['--list-packets', data_path('test_key_edge_cases/key-empty-packets.pgp')] - ret, out, err = run_proc(RNP, params) - if ret == 0: - raise_err('packet listing not failed', err) + ret, out, _ = run_proc(RNP, params) + self.assertNotEqual(ret, 0, 'packet listing not failed') compare_file_ex(data_path('test_key_edge_cases/key-empty-packets.txt'), out, 'key-empty-packets listing mismatch') # List empty key packets json params = ['--list-packets', '--json', data_path('test_key_edge_cases/key-empty-packets.pgp')] - ret, out, err = run_proc(RNP, params) - if ret == 0: - raise_err('packet listing not failed', err) + ret, _, _ = run_proc(RNP, params) + self.assertNotEqual(ret, 0, 'packet listing not failed') # List empty uid - params = ['--list-packets', data_path('test_key_edge_cases/key-empty-uid.pgp')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + params = ['--list-packets', KEY_EMPTY_UID] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_key_edge_cases/key-empty-uid.txt'), out, 'key-empty-uid listing mismatch') # List empty uid with raw packet contents - params = ['--list-packets', '--raw', data_path('test_key_edge_cases/key-empty-uid.pgp')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + params = ['--list-packets', '--raw', KEY_EMPTY_UID] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_key_edge_cases/key-empty-uid-raw.txt'), out, 'key-empty-uid-raw listing mismatch') # List empty uid packet contents to JSON - params = ['--list-packets', '--json', data_path('test_key_edge_cases/key-empty-uid.pgp')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + params = ['--list-packets', '--json', KEY_EMPTY_UID] + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_key_edge_cases/key-empty-uid.json'), out, 'key-empty-uid json listing mismatch') # List experimental subpackets params = ['--list-packets', data_path('test_key_edge_cases/key-subpacket-101-110.pgp')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_key_edge_cases/key-subpacket-101-110.txt'), out, 'key-subpacket-101-110 listing mismatch') # List experimental subpackets JSON params = ['--list-packets', '--json', data_path('test_key_edge_cases/key-subpacket-101-110.pgp')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_key_edge_cases/key-subpacket-101-110.json'), out, 'key-subpacket-101-110 json listing mismatch') # List malformed signature params = ['--list-packets', data_path('test_key_edge_cases/key-malf-sig.pgp')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_key_edge_cases/key-malf-sig.txt'), out, 'key-malf-sig listing mismatch') # List malformed signature JSON params = ['--list-packets', '--json', data_path('test_key_edge_cases/key-malf-sig.pgp')] - ret, out, err = run_proc(RNP, params) - if ret != 0: - raise_err('packet listing failed', err) + ret, out, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, PKT_LIST_FAILED) compare_file_ex(data_path('test_key_edge_cases/key-malf-sig.json'), out, 'key-malf-sig json listing mismatch') - return - def test_debug_log(self): run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '--list-keys', '--debug', '--all']) run_proc(RNPK, ['--homedir', data_path('keyrings/2'), '--list-keys', '--debug', '--all']) run_proc(RNPK, ['--homedir', data_path('keyrings/3'), '--list-keys', '--debug', '--all']) - run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), + run_proc(RNPK, ['--homedir', data_path(SECRING_G10), '--list-keys', '--debug', '--all']) - return def test_pubring_loading(self): + NO_PUBRING = r'(?s)^.*warning: keyring at path \'.*/pubring.gpg\' doesn\'t exist.*$' + NO_USERID = 'No userid or default key for operation' + test_dir = tempfile.mkdtemp(prefix='rnpctmp') - test_data = data_path('test_messages/message.txt') - output = path.join(test_dir, 'output') + test_data = data_path(MSG_TXT) + output = os.path.join(test_dir, 'output') params = ['--symmetric', '--password', 'pass', '--homedir', test_dir, test_data, '--output', output] - ret, _, err = run_proc(RNP, ['--encrypt'] + params) - if not (ret == 2 and 'wrong pubring path' in err): - raise_err("encrypt w/o pubring didn't fail", err) + self.assertEqual(ret, 1, 'encrypt w/o pubring didn\'t fail') + self.assertRegex(err, NO_PUBRING, 'wrong no-keyring message') + self.assertIn(NO_USERID, err, 'Unexpected no key output') + self.assertIn('Failed to build recipients key list', err, 'Unexpected key list output') ret, _, err = run_proc(RNP, ['--sign'] + params) - if not (ret == 2 and 'wrong pubring path' in err): - raise_err("sign w/o pubring didn't fail", err) + self.assertEqual(ret, 1, 'sign w/o pubring didn\'t fail') + self.assertRegex(err, NO_PUBRING, 'wrong failure output') + self.assertIn(NO_USERID, err, 'wrong no userid message') + self.assertIn('Failed to build signing keys list', err, 'wrong signing list failure message') ret, _, err = run_proc(RNP, ['--clearsign'] + params) - if not (ret == 2 and 'wrong pubring path' in err): - raise_err("clearsign w/o pubring didn't fail", err) + self.assertEqual(ret, 1, 'clearsign w/o pubring didn\'t fail') + self.assertRegex(err, NO_PUBRING, 'wrong clearsign no pubring message') + self.assertIn(NO_USERID, err, 'Unexpected clearsign no key output') + self.assertIn('Failed to build signing keys list', err, 'Unexpected clearsign key list output') - ret, _, err = run_proc(RNP, params) - if ret != 0: - raise_err("symmetric w/o pubring failed", err) + ret, _, _ = run_proc(RNP, params) + self.assertEqual(ret, 0, 'symmetric w/o pubring failed') shutil.rmtree(test_dir) def test_homedir_accessibility(self): - ret, _, _ = run_proc(RNPK, ['--homedir', path.join(RNPDIR, 'non-existing'), '--generate', '--password=none']) - if ret == 0: - raise_err("failed to check for homedir accessibility") - os.mkdir(path.join(RNPDIR, 'existing'), 0o700) - ret, _, _ = run_proc(RNPK, ['--homedir', path.join(RNPDIR, 'existing'), '--generate', '--password=none']) - if ret != 0: - raise_err("failed to use writeable and existing homedir") + ret, _, _ = run_proc(RNPK, ['--homedir', os.path.join(RNPDIR, 'non-existing'), '--generate', '--password=none']) + self.assertNotEqual(ret, 0, 'failed to check for homedir accessibility') + os.mkdir(os.path.join(RNPDIR, 'existing'), 0o700) + ret, _, _ = run_proc(RNPK, ['--homedir', os.path.join(RNPDIR, 'existing'), '--generate', '--password=none']) + self.assertEqual(ret, 0, 'failed to use writeable and existing homedir') def test_no_home_dir(self): home = os.environ['HOME'] del os.environ['HOME'] ret, _, _ = run_proc(RNP, ['-v', 'non-existing.pgp']) os.environ['HOME'] = home - if ret != 2: - raise_err("failed to run without HOME env variable") + self.assertEqual(ret, 2, 'failed to run without HOME env variable') + + def test_exit_codes(self): + ret, _, _ = run_proc(RNP, ['--homedir', RNPDIR, '--help']) + self.assertEqual(ret, 0, 'invalid exit code of \'rnp --help\'') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--help']) + self.assertEqual(ret, 0, 'invalid exit code of \'rnpkeys --help\'') + ret, _, _ = run_proc(RNP, ['--homedir', RNPDIR, '--unknown-option', '--help']) + self.assertNotEqual(ret, 0, 'rnp should return non-zero exit code for unknown command line options') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--unknown-option', '--help']) + self.assertNotEqual(ret, 0, 'rnpkeys should return non-zero exit code for unknown command line options') + + def test_input_from_specifier(self): + KEY_LIST = r'(?s)^.*' \ + r'1 key found.*' \ + r'pub .*255/EdDSA.*0451409669ffde3c.*' \ + r'73edcc9119afc8e2dbbdcde50451409669ffde3c.*$' + NO_KEY_LIST = r'(?s)^.*' \ + r'Key\(s\) not found.*$' + WRONG_VAR = r'(?s)^.*' \ + r'Failed to get value of the environment variable \'SOMETHING_UNSET\'.*' \ + r'Failed to create input for env:SOMETHING_UNSET.*$' + WRONG_DATA = r'(?s)^.*' \ + r'failed to import key\(s\) from env:KEY_FILE, stopping.*$' + PGP_MSG = r'(?s)^.*' \ + r'-----BEGIN PGP MESSAGE-----.*' \ + r'-----END PGP MESSAGE-----.*$' + ENV_KEY = 'env:KEY_FILE' + + clear_keyrings() + # Import key from the stdin + ktext = file_text(data_path(KEY_ALICE_SEC)) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', '-'], ktext) + self.assertEqual(ret, 0, 'failed to import key from stdin') + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0, KEY_LIST_FAILED) + self.assertRegex(out, KEY_LIST, KEY_LIST_WRONG) + # Cleanup and import key from the env variable + clear_keyrings() + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertNotEqual(ret, 0, 'no key list failed') + self.assertRegex(out, NO_KEY_LIST, KEY_LIST_WRONG) + # Pass unset variable + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', 'env:SOMETHING_UNSET']) + self.assertNotEqual(ret, 0, 'key import from env must fail') + self.assertRegex(err, WRONG_VAR, 'wrong output') + # Pass incorrect value in environment variable + os.environ['KEY_FILE'] = "something" + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', ENV_KEY]) + self.assertNotEqual(ret, 0, 'key import failed') + self.assertRegex(err, WRONG_DATA, 'wrong output') + # Now import the correct key + os.environ['KEY_FILE'] = ktext + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', ENV_KEY]) + self.assertEqual(ret, 0, 'key import failed') + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0, KEY_LIST_FAILED) + self.assertRegex(out, KEY_LIST, KEY_LIST_WRONG) + + # Sign message from the stdin, using the env keyfile + ret, out, _ = run_proc(RNP, ['-s', '-', '--password', 'password', '--armor', '--keyfile', ENV_KEY], 'Message to sign') + self.assertEqual(ret, 0, 'Message signing failed') + self.assertRegex(out, PGP_MSG, 'wrong signing output') + os.environ['SIGN_MSG'] = out + # Verify message from the env variable + ret, out, _ = run_proc(RNP, ['-d', 'env:SIGN_MSG', '--keyfile', ENV_KEY]) + self.assertEqual(ret, 0, 'Message verification failed') + self.assertEqual(out, 'Message to sign', 'wrong verification output') + + def test_output_to_specifier(self): + src, enc, encasc, dec = reg_workfiles('source', '.txt', EXT_PGP, EXT_ASC, '.dec') + with open(src, 'w+') as f: + f.write('Hello world') + # Encrypt file and make sure result is stored with .pgp extension + ret, out, _ = run_proc(RNP, ['-c', src, '--password', 'password']) + self.assertEqual(ret, 0, ENC_FAILED) + ret, _, _ = run_proc(RNP, ['--homedir', RNPDIR, '-d', enc, '--output', dec, '--password', 'password']) + self.assertEqual(ret, 0, DEC_FAILED) + self.assertEqual(file_text(src), file_text(dec), DEC_DIFFERS) + remove_files(enc, dec) + # Encrypt file with armor and make sure result is stored with .asc extension + ret, _, _ = run_proc(RNP, ['-c', src, '--armor', '--password', 'password']) + self.assertEqual(ret, 0, ENC_FAILED) + ret, out, _ = run_proc(RNP, ['--homedir', RNPDIR, '-d', encasc, '--output', '-', '--password', 'password']) + self.assertEqual(ret, 0, DEC_FAILED) + self.assertEqual(file_text(src), out, DEC_DIFFERS) + remove_files(encasc) + # Encrypt file and write result to the stdout + ret, out, _ = run_proc(RNP, ['-c', src, '--armor', '--output', '-', '--password', 'password']) + self.assertEqual(ret, 0, ENC_FAILED) + ret, _, _ = run_proc(RNP, ['--homedir', RNPDIR, '-d', '--output', dec, '--password', 'password', '-'], out) + self.assertEqual(ret, 0, DEC_FAILED) + self.assertEqual(file_text(src), file_text(dec), DEC_DIFFERS) + remove_files(dec) + # Encrypt file and write armored result to the stdout + ret, out, _ = run_proc(RNP, ['-c', src, '--armor','--output', '-', '--password', 'password']) + self.assertEqual(ret, 0, ENC_FAILED) + ret, out, _ = run_proc(RNP, ['--homedir', RNPDIR, '-d', '--output', '-', '--password', 'password', '-'], out) + self.assertEqual(ret, 0, DEC_FAILED) + self.assertEqual(file_text(src), out, DEC_DIFFERS) + # Encrypt stdin and write result to the stdout + srctxt = file_text(src) + ret, out, _ = run_proc(RNP, ['-c', '--armor', '--password', 'password'], srctxt) + self.assertEqual(ret, 0, ENC_FAILED) + ret, out, _ = run_proc(RNP, ['--homedir', RNPDIR, '-d', '--password', 'password'], out) + self.assertEqual(ret, 0, DEC_FAILED) + self.assertEqual(out, srctxt, DEC_DIFFERS) + # Encrypt stdin and attempt to write to non-existing dir + ret, _, err = run_proc(RNP, ['-c', '--armor', '--password', 'password', '--output', 'nonexisting/output.pgp'], srctxt) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*init_file_dest.*failed to create file.*output.pgp.*Error 2.*$') + self.assertNotRegex(err, r'(?s)^.*failed to initialize encryption.*$') + self.assertRegex(err, r'(?s)^.*failed to open source or create output.*$') + # Sign stdin and then verify it using non-existing directory for output + ret, out, _ = run_proc(RNP, ['--homedir', RNPDIR, '--armor', '--password', 'password', '-s'], srctxt) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*BEGIN PGP MESSAGE.*END PGP MESSAGE.*$') + ret, _, err = run_proc(RNP, ['--homedir', RNPDIR, '-v', '--output', 'nonexisting/output.pgp'], out) + self.assertEqual(ret, 1) + self.assertRegex(err, r'(?s)^.*init_file_dest.*failed to create file.*output.pgp.*Error 2.*$') + + def test_empty_keyrings(self): + NO_KEYRING = r'(?s)^.*' \ + r'warning: keyring at path \'.*/\.rnp/pubring.gpg\' doesn\'t exist.*' \ + r'warning: keyring at path \'.*/\.rnp/secring.gpg\' doesn\'t exist.*$' + EMPTY_KEYRING = r'(?s)^.*' \ + r'warning: no keys were loaded from the keyring \'.*/\.rnp/pubring.gpg\'.*' \ + r'warning: no keys were loaded from the keyring \'.*/\.rnp/secring.gpg\'.*$' + PUB_IMPORT= r'(?s)^.*pub\s+255/EdDSA 0451409669ffde3c .* \[SC\].*$' + EMPTY_SECRING = r'(?s)^.*' \ + r'warning: no keys were loaded from the keyring \'.*/\.rnp/secring.gpg\'.*$' + SEC_IMPORT= r'(?s)^.*sec\s+255/EdDSA 0451409669ffde3c .* \[SC\].*$' + + os.rename(RNPDIR, RNPDIR + '-old') + home = os.environ['HOME'] + os.environ['HOME'] = WORKDIR + try: + self.assertFalse(os.path.isdir(RNPDIR), '.rnp directory should not exists') + src, enc, dec = reg_workfiles('source', '.txt', EXT_PGP, '.dec') + random_text(src, 2000) + # Run symmetric encryption/decryption without .rnp home directory + ret, _, err = run_proc(RNP, ['-c', src, '--password', 'password']) + self.assertEqual(ret, 0, 'Symmetric encryption without home failed') + self.assertNotRegex(err, NO_KEYRING, 'No keyring msg in encryption output') + ret, _, err = run_proc(RNP, ['-d', enc, '--password', 'password', '--output', dec]) + self.assertEqual(ret, 0, 'Symmetric decryption without home failed') + self.assertRegex(err, NO_KEYRING, 'No keyring msg in decryption output') + self.assertIn(WORKDIR, err, 'No workdir in decryption output') + compare_files(src, dec, DEC_DIFFERS) + remove_files(enc, dec) + # Import key without .rnp home directory + ret, out, err = run_proc(RNPK, ['--import', data_path(KEY_ALICE_PUB)]) + self.assertEqual(ret, 0, 'Key import failed without home') + self.assertRegex(err, NO_KEYRING, 'No keyring msg in key import output') + self.assertIn(WORKDIR, err, 'No workdir in key import output') + self.assertRegex(out, PUB_IMPORT, 'Wrong key import output') + ret, out, err = run_proc(RNPK, ['--import', data_path(KEY_ALICE_SEC)]) + self.assertEqual(ret, 0, 'Secret key import without home failed') + self.assertNotRegex(err, NO_KEYRING, 'no keyring message in key import output') + self.assertRegex(err, EMPTY_SECRING, 'no empty secrin in key import output') + self.assertIn(WORKDIR, err, 'no workdir in key import output') + self.assertRegex(out, SEC_IMPORT, 'Wrong secret key import output') + # Run with empty .rnp home directory + shutil.rmtree(RNPDIR, ignore_errors=True) + os.mkdir(RNPDIR, 0o700) + ret, _, err = run_proc(RNP, ['-c', src, '--password', 'password']) + self.assertEqual(ret, 0) + self.assertNotRegex(err, NO_KEYRING) + ret, out, err = run_proc(RNP, ['-d', enc, '--password', 'password', '--output', dec]) + self.assertEqual(ret, 0, 'Symmetric decryption failed') + self.assertRegex(err, NO_KEYRING, 'No keyring message in decryption output') + self.assertIn(WORKDIR, err, 'No workdir in decryption output') + compare_files(src, dec, DEC_DIFFERS) + remove_files(enc, dec) + # Import key with empty .rnp home directory + ret, out, err = run_proc(RNPK, ['--import', data_path(KEY_ALICE_PUB)]) + self.assertEqual(ret, 0, 'Public key import with empty home failed') + self.assertRegex(err, NO_KEYRING, 'No keyring message in key import output') + self.assertIn(WORKDIR, err, 'No workdir in key import output') + self.assertRegex(out, PUB_IMPORT, 'Wrong pub key import output') + ret, out, err = run_proc(RNPK, ['--import', data_path(KEY_ALICE_SEC)]) + self.assertEqual(ret, 0, 'Secret key import failed') + self.assertNotRegex(err, NO_KEYRING, 'No-keyring message in secret key import output') + self.assertRegex(err, EMPTY_SECRING, 'No empty secring msg in secret key import output') + self.assertIn(WORKDIR, err, 'No workdir in secret key import output') + self.assertRegex(out, SEC_IMPORT, 'wrong secret key import output') + # Run with .rnp home directory with empty keyrings + shutil.rmtree(RNPDIR, ignore_errors=True) + os.mkdir(RNPDIR, 0o700) + random_text(os.path.join(RNPDIR, PUBRING), 0) + random_text(os.path.join(RNPDIR, SECRING), 0) + ret, out, err = run_proc(RNP, ['-c', src, '--password', 'password']) + self.assertEqual(ret, 0, 'Symmetric encryption failed') + self.assertNotRegex(err, EMPTY_KEYRING, 'Invalid encryption output') + ret, out, err = run_proc(RNP, ['-d', enc, '--password', 'password', '--output', dec]) + self.assertEqual(ret, 0, 'Symmetric decryption failed') + self.assertRegex(err, EMPTY_KEYRING, 'wrong decryption output') + self.assertIn(WORKDIR, err, 'wrong decryption output') + compare_files(src, dec, DEC_DIFFERS) + remove_files(enc, dec) + # Import key with empty keyrings in .rnp home directory + ret, out, err = run_proc(RNPK, ['--import', data_path(KEY_ALICE_PUB)]) + self.assertEqual(ret, 0, 'Public key import failed') + self.assertRegex(err, EMPTY_KEYRING, 'No empty keyring msg in key import output') + self.assertIn(WORKDIR, err, 'No workdir in empty keyring key import output') + self.assertRegex(out, PUB_IMPORT, 'Wrong pubkey import output') + ret, out, err = run_proc(RNPK, ['--import', data_path(KEY_ALICE_SEC)]) + self.assertEqual(ret, 0, 'Secret key import failed') + self.assertNotRegex(err, EMPTY_KEYRING, 'No empty keyring in key import output') + self.assertRegex(err, EMPTY_SECRING, 'No empty secring in key import output') + self.assertIn(WORKDIR, err, 'wrong key import output') + self.assertRegex(out, SEC_IMPORT, 'wrong secret key import output') + finally: + os.environ['HOME'] = home + shutil.rmtree(RNPDIR, ignore_errors=True) + os.rename(RNPDIR + '-old', RNPDIR) + clear_workfiles() + + def test_alg_aliases(self): + src, enc = reg_workfiles('source', '.txt', EXT_PGP) + with open(src, 'w+') as f: + f.write('Hello world') + # Encrypt file but forget to pass cipher name + ret, _, err = run_proc(RNP, ['-c', src, '--password', 'password', '--cipher']) + self.assertNotEqual(ret, 0) + # Encrypt file using the unknown symmetric algorithm + ret, _, err = run_proc(RNP, ['-c', src, '--cipher', 'bad', '--password', 'password']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Unsupported encryption algorithm: bad.*$') + # Encrypt file but forget to pass hash algorithm name + ret, _, err = run_proc(RNP, ['-c', src, '--password', 'password', '--hash']) + self.assertNotEqual(ret, 0) + # Encrypt file using the unknown hash algorithm + ret, _, err = run_proc(RNP, ['-c', src, '--hash', 'bad', '--password', 'password']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Unsupported hash algorithm: bad.*$') + # Encrypt file using the AES algorithm instead of AES-128 + ret, _, err = run_proc(RNP, ['-c', src, '--cipher', 'AES', '--password', 'password']) + self.assertEqual(ret, 0) + self.assertNotRegex(err, r'(?s)^.*Warning, unsupported encryption algorithm: AES.*$') + self.assertNotRegex(err, r'(?s)^.*Unsupported encryption algorithm: AES.*$') + # Make sure AES-128 was used + ret, out, _ = run_proc(RNP, ['--list-packets', enc]) + self.assertEqual(ret, 0) + self.assertRegex(out,r'(?s)^.*Symmetric-key encrypted session key packet.*symmetric algorithm: 7 \(AES-128\).*$') + remove_files(enc) + # Encrypt file using the 3DES instead of tripledes + ret, _, err = run_proc(RNP, ['-c', src, '--cipher', '3DES', '--password', 'password']) + self.assertEqual(ret, 0) + self.assertNotRegex(err, r'(?s)^.*Warning, unsupported encryption algorithm: 3DES.*$') + self.assertNotRegex(err, r'(?s)^.*Unsupported encryption algorithm: 3DES.*$') + # Make sure 3DES was used + ret, out, _ = run_proc(RNP, ['--list-packets', enc]) + self.assertEqual(ret, 0) + self.assertRegex(out,r'(?s)^.*Symmetric-key encrypted session key packet.*symmetric algorithm: 2 \(TripleDES\).*$') + remove_files(enc) + # Use ripemd-160 hash instead of RIPEMD160 + ret, _, err = run_proc(RNP, ['-c', src, '--hash', 'ripemd-160', '--password', 'password']) + self.assertEqual(ret, 0) + self.assertNotRegex(err, r'(?s)^.*Unsupported hash algorithm: ripemd-160.*$') + # Make sure RIPEMD160 was used + ret, out, _ = run_proc(RNP, ['--list-packets', enc]) + self.assertEqual(ret, 0) + self.assertRegex(out,r'(?s)^.*Symmetric-key encrypted session key packet.*s2k hash algorithm: 3 \(RIPEMD160\).*$') + remove_files(enc) + + def test_core_dumps(self): + CORE_DUMP = r'(?s)^.*warning: core dumps may be enabled, sensitive data may be leaked to disk.*$' + NO_CORE_DUMP = r'(?s)^.*warning: --coredumps doesn\'t make sense on windows systems.*$' + # Check rnpkeys for the message + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys']) + self.assertEqual(ret, 0) + self.assertNotRegex(err, CORE_DUMP) + # Check rnp for the message + ret, _, err = run_proc(RNP, ['--homedir', RNPDIR, '--armor', '--password', 'password', '-c'], 'message') + self.assertEqual(ret, 0) + self.assertNotRegex(err, CORE_DUMP) + # Enable coredumps for rnpkeys + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys', '--coredumps']) + self.assertEqual(ret, 0) + if is_windows(): + self.assertNotRegex(err, CORE_DUMP) + self.assertRegex(err, NO_CORE_DUMP) + else: + self.assertRegex(err, CORE_DUMP) + self.assertNotRegex(err, NO_CORE_DUMP) + # Enable coredumps for rnp + ret, _, err = run_proc(RNP, ['--homedir', RNPDIR, '--armor', '--password', 'password', '-c', '--coredumps'], 'message') + self.assertEqual(ret, 0) + if is_windows(): + self.assertNotRegex(err, CORE_DUMP) + self.assertRegex(err, NO_CORE_DUMP) + else: + self.assertRegex(err, CORE_DUMP) + self.assertNotRegex(err, NO_CORE_DUMP) + + def test_backend_version(self): + BOTAN_BACKEND_VERSION = r'(?s)^.*.' \ + 'Backend: Botan.*' \ + 'Backend version: ([a-zA-z\.0-9]+).*$' + OPENSSL_BACKEND_VERSION = r'(?s)^.*' \ + 'Backend: OpenSSL.*' \ + 'Backend version: ([a-zA-z\.0-9]+).*$' + # Run without parameters and make sure it matches + ret, out, _ = run_proc(RNP, []) + self.assertNotEqual(ret, 0) + match = re.match(BOTAN_BACKEND_VERSION, out) or re.match(OPENSSL_BACKEND_VERSION, out) + self.assertTrue(match) + # Run with version parameters + ret, out, _ = run_proc(RNP, ['--version']) + self.assertEqual(ret, 0) + match = re.match(BOTAN_BACKEND_VERSION, out) + backend_prog = 'botan' + if not match: + match = re.match(OPENSSL_BACKEND_VERSION, out) + backend_prog = 'openssl' + self.assertTrue(match) + # check that botan or openssl executable binary exists in $PATH + backen_prog_ext = shutil.which(backend_prog) + if backen_prog_ext is not None: + ret, out, _ = run_proc(backen_prog_ext, ['version']) + self.assertEqual(ret, 0) + self.assertIn(match.group(1), out) + + def test_wrong_mpi_bit_count(self): + WRONG_MPI_BITS = r'(?s)^.*Warning! Wrong mpi bit count: got [0-9]+, but actual is [0-9]+.*$' + # Make sure message is not displayed on normal keys + ret, _, err = run_proc(RNP, ['--list-packets', data_path(PUBRING_1)]) + self.assertEqual(ret, 0) + self.assertNotRegex(err, WRONG_MPI_BITS) + # Make sure message is displayed on wrong mpi + ret, _, err = run_proc(RNP, ['--list-packets', data_path('test_key_edge_cases/alice-wrong-mpi-bit-count.pgp')]) + self.assertEqual(ret, 0) + self.assertRegex(err, WRONG_MPI_BITS) + + def test_eddsa_small_x(self): + os.rename(RNPDIR, RNPDIR + '-old') + home = os.environ['HOME'] + os.environ['HOME'] = WORKDIR + try: + self.assertFalse(os.path.isdir(RNPDIR), '.rnp directory should not exists') + src, sig, ver = reg_workfiles('source', '.txt', EXT_PGP, '.dec') + random_text(src, 2000) + # load just public key and verify pre-signed message + ret, _, _ = run_proc(RNPK, ['--import', data_path('test_key_edge_cases/key-eddsa-small-x-pub.asc')]) + self.assertEqual(ret, 0) + ret, _, err = run_proc(RNP, ['--verify', data_path('test_messages/message.txt.sign-small-eddsa-x')]) + self.assertEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Good signature made .*using EdDSA key 7bc55b9bdce36e18.*$') + # load secret key and sign message + ret, out, _ = run_proc(RNPK, ['--import', data_path('test_key_edge_cases/key-eddsa-small-x-sec.asc')]) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*sec.*255/EdDSA.*7bc55b9bdce36e18.*eddsa_small_x.*ssb.*c6c35ea115368a0b.*$') + ret, _, _ = run_proc(RNP, ['--password', PASSWORD, '--sign', src, '--output', sig]) + self.assertEqual(ret, 0) + # verify back + ret, _, err = run_proc(RNP, ['--verify', sig, '--output', ver]) + self.assertEqual(ret, 0) + self.assertEqual(file_text(src), file_text(ver)) + self.assertRegex(err, r'(?s)^.*Good signature made .*using EdDSA key 7bc55b9bdce36e18.*$') + # verify back with GnuPG + os.remove(ver) + gpg_import_pubring(data_path('test_key_edge_cases/key-eddsa-small-x-pub.asc')) + gpg_verify_file(sig, ver, 'eddsa_small_x') + finally: + os.environ['HOME'] = home + shutil.rmtree(RNPDIR, ignore_errors=True) + os.rename(RNPDIR + '-old', RNPDIR) + clear_workfiles() + + def test_cv25519_bit_fix(self): + RE_NOT_25519 = r'(?s)^.*Error: specified key is not Curve25519 ECDH subkey.*$' + # Import and tweak non-protected secret key + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_25519_NOTWEAK_SEC)]) + self.assertEqual(ret, 0) + # Check some --edit-key invalid options combinations + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*You need to specify a key or subkey to edit.*$') + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key', '3176fc1486aa2528']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*You should specify at least one editing option for --edit-key.*$') + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key', '--check-cv25519-bits']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*You need to specify a key or subkey to edit.*$') + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key', '--check-cv25519-bits', 'key']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Secret keys matching \'key\' not found.*$') + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key', '--check-cv25519-bits', 'eddsa-25519-non-tweaked']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, RE_NOT_25519) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key', '--check-cv25519-bits', '3176fc1486aa2528']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, RE_NOT_25519) + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--notty', '--edit-key', '--check-cv25519-bits', '950ee0cd34613dba']) + self.assertNotEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*Warning: Cv25519 key bits need fixing.*$') + # Tweak bits + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key', '--fix-cv25519-bits', '3176fc1486aa2528']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, RE_NOT_25519) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--edit-key', '--fix-cv25519-bits', '950ee0cd34613dba']) + self.assertEqual(ret, 0) + # Make sure bits are correctly tweaked and key may be used to decrypt and imported to GnuPG + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--notty', '--edit-key', '--check-cv25519-bits', '950ee0cd34613dba']) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*Cv25519 key bits are set correctly and do not require fixing.*$') + ret, _, _ = run_proc(RNP, ['--homedir', RNPDIR, '-d', data_path(MSG_ES_25519)]) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', os.path.join(RNPDIR, SECRING)]) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '-d', data_path(MSG_ES_25519)]) + self.assertEqual(ret, 0) + # Remove key + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--yes', '--delete-secret-key', 'dde0ee539c017d2bd3f604a53176fc1486aa2528']) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '--force', 'dde0ee539c017d2bd3f604a53176fc1486aa2528']) + self.assertEqual(ret, 0) + # Make sure protected secret key works the same way + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_edge_cases/key-25519-non-tweaked-sec-prot.asc')]) + self.assertEqual(ret, 0) + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--password', 'wrong', '--edit-key', '--check-cv25519-bits', '950ee0cd34613dba']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Error: failed to unlock key. Did you specify valid password\\?.*$') + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--password', 'password', '--notty', '--edit-key', '--check-cv25519-bits', '950ee0cd34613dba']) + self.assertNotEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*Warning: Cv25519 key bits need fixing.*$') + # Tweak bits + ret, _, err = run_proc(RNPK, ['--homedir', RNPDIR, '--password', 'wrong', '--edit-key', '--fix-cv25519-bits', '950ee0cd34613dba']) + self.assertNotEqual(ret, 0) + self.assertRegex(err, r'(?s)^.*Error: failed to unlock key. Did you specify valid password\\?.*$') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--password', 'password', '--edit-key', '--fix-cv25519-bits', '950ee0cd34613dba']) + self.assertEqual(ret, 0) + # Make sure key is protected with the same options + ret, out, _ = run_proc(RNP, ['--list-packets', os.path.join(RNPDIR, SECRING)]) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*Secret subkey packet.*254.*AES-256.*3.*SHA256.*58720256.*0x950ee0cd34613dba.*$') + # Make sure bits are correctly tweaked and key may be used to decrypt and imported to GnuPG + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--notty', '--password', 'password', '--edit-key', '--check-cv25519-bits', '950ee0cd34613dba']) + self.assertEqual(ret, 0) + self.assertRegex(out, r'(?s)^.*Cv25519 key bits are set correctly and do not require fixing.*$') + ret, _, _ = run_proc(RNP, ['--homedir', RNPDIR, '--password', 'password', '-d', data_path(MSG_ES_25519)]) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--batch', '--passphrase', 'password', '--import', os.path.join(RNPDIR, SECRING)]) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, GPG_LOOPBACK, '--batch', '--passphrase', 'password', + '--trust-model', 'always', '-d', data_path(MSG_ES_25519)]) + self.assertEqual(ret, 0) + # Remove key + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--yes', '--delete-secret-key', 'dde0ee539c017d2bd3f604a53176fc1486aa2528']) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', '--force', 'dde0ee539c017d2bd3f604a53176fc1486aa2528']) + self.assertEqual(ret, 0) class Encryption(unittest.TestCase): ''' @@ -2009,11 +2621,11 @@ # Ciphers list tro try during encryption. None will use default CIPHERS = [None, 'AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256', 'IDEA', '3DES', 'CAST5', 'BLOWFISH'] - SIZES = [20, 40, 120, 600, 1000, 5000, 20000, 150000, 1000000] + SIZES = [20, 40, 120, 600, 1000, 5000, 20000, 250000] # Compression parameters to try during encryption(s) Z = [[None, 0], ['zip'], ['zlib'], ['bzip2'], [None, 1], [None, 9]] # Number of test runs - each run picks next encryption algo and size, wrapping on array - RUNS = 60 + RUNS = 20 @classmethod def setUpClass(cls): @@ -2024,6 +2636,8 @@ rnp_genkey_rsa('dummy2@rnp', 1024) gpg_import_pubring() gpg_import_secring() + if not RNP_TWOFISH: + Encryption.CIPHERS.remove('TWOFISH') Encryption.CIPHERS_R = list_upto(Encryption.CIPHERS, Encryption.RUNS) Encryption.SIZES_R = list_upto(Encryption.SIZES, Encryption.RUNS) Encryption.Z_R = list_upto(Encryption.Z, Encryption.RUNS) @@ -2057,18 +2671,20 @@ rnp_sym_encryption_rnp_to_gpg(size, cipher, z) def test_sym_encryption__rnp_aead(self): - AEAD_C = list_upto(['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', - 'CAMELLIA192', 'CAMELLIA256'], Encryption.RUNS) + if not RNP_AEAD: + print('AEAD is not available for RNP - skipping.') + return + CIPHERS = ['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256'] + if not RNP_TWOFISH: + CIPHERS.remove('TWOFISH') + AEAD_C = list_upto(CIPHERS, Encryption.RUNS) AEAD_M = list_upto([None, 'eax', 'ocb'], Encryption.RUNS) - AEAD_B = list_upto([None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18, - 24, 30, 40, 50, 56], Encryption.RUNS) - - usegpg = gpg_supports_aead() + AEAD_B = list_upto([None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16], Encryption.RUNS) # Encrypt and decrypt cleartext using the AEAD for size, cipher, aead, bits, z in zip(Encryption.SIZES_R, AEAD_C, AEAD_M, AEAD_B, Encryption.Z_R): - rnp_sym_encryption_rnp_aead(size, cipher, z, [aead, bits], usegpg) + rnp_sym_encryption_rnp_aead(size, cipher, z, [aead, bits], GPG_AEAD) def test_encryption_multiple_recipients(self): USERIDS = ['key1@rnp', 'key2@rnp', 'key3@rnp'] @@ -2084,20 +2700,22 @@ KEYPSWD = tuple((t1, t2) for t1 in range(len(USERIDS) + 1) for t2 in range(len(PASSWORDS) + 1)) KEYPSWD = list_upto(KEYPSWD, Encryption.RUNS) - if gpg_supports_aead(): + if GPG_AEAD and RNP_AEAD: AEADS = list_upto([None, [None], ['eax'], ['ocb']], Encryption.RUNS) else: AEADS = list_upto([None], Encryption.RUNS) src, dst, dec = reg_workfiles('cleartext', '.txt', '.rnp', '.dec') # Generate random file of required size - random_text(src, 128000) + random_text(src, 65500) for kpswd, aead in zip(KEYPSWD, AEADS): keynum, pswdnum = kpswd if (keynum == 0) and (pswdnum == 0): continue - + # For CFB mode there is ~5% probability that GnuPG will attempt to decrypt + # message's SESK with a wrong password, see T3795 on dev.gnupg.org + skipgpg = not aead and ((pswdnum > 1) or ((pswdnum > 0) and (keynum > 0))) uids = USERIDS[:keynum] if keynum else None pswds = PASSWORDS[:pswdnum] if pswdnum else None @@ -2105,23 +2723,20 @@ # Decrypt file with each of the keys, we have different password for each key for pswd in KEYPASS[:keynum]: - gpg_decrypt_file(dst, dec, pswd) - gpg_agent_clear_cache() - remove_files(dec) + if not skipgpg: + gpg_decrypt_file(dst, dec, pswd) + gpg_agent_clear_cache() + remove_files(dec) rnp_decrypt_file(dst, dec, '\n'.join([pswd] * 5)) + remove_files(dec) - # GPG decrypts only with first password, see T3795 - if (not aead) and pswdnum: + # Decrypt file with each of the passwords (with gpg only first password is checked) + if skipgpg: gpg_decrypt_file(dst, dec, PASSWORDS[0]) - gpg_agent_clear_cache + gpg_agent_clear_cache() remove_files(dec) - # Decrypt file with each of the passwords for pswd in PASSWORDS[:pswdnum]: - if aead: - gpg_decrypt_file(dst, dec, pswd) - gpg_agent_clear_cache() - remove_files(dec) rnp_decrypt_file(dst, dec, '\n'.join([pswd] * 5)) remove_files(dec) @@ -2133,8 +2748,10 @@ USERIDS = ['enc-sign1@rnp', 'enc-sign2@rnp', 'enc-sign3@rnp'] KEYPASS = ['encsign1pass', 'encsign2pass', 'encsign3pass'] PASSWORDS = ['password1', 'password2', 'password3'] - AEAD_C = list_upto(['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', - 'CAMELLIA192', 'CAMELLIA256'], Encryption.RUNS) + CIPHERS = ['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256'] + if not RNP_TWOFISH: + CIPHERS.remove('TWOFISH') + AEAD_C = list_upto(CIPHERS, Encryption.RUNS) # Generate multiple keys and import to GnuPG for uid, pswd in zip(USERIDS, KEYPASS): rnp_genkey_rsa(uid, 1024, pswd) @@ -2146,7 +2763,7 @@ KEYPSWD = tuple((t1, t2) for t1 in range(1, len(USERIDS) + 1) for t2 in range(len(PASSWORDS) + 1)) KEYPSWD = list_upto(KEYPSWD, Encryption.RUNS) - if gpg_supports_aead(): + if GPG_AEAD and RNP_AEAD: AEADS = list_upto([None, [None], ['eax'], ['ocb']], Encryption.RUNS) else: AEADS = list_upto([None], Encryption.RUNS) @@ -2154,7 +2771,7 @@ src, dst, dec = reg_workfiles('cleartext', '.txt', '.rnp', '.dec') # Generate random file of required size - random_text(src, 128000) + random_text(src, 65500) for i in range(0, Encryption.RUNS): signers = USERIDS[:SIGNERS[i]] @@ -2165,25 +2782,32 @@ aead = AEADS[i] z = ZS[i] cipher = AEAD_C[i] + # For CFB mode there is ~5% probability that GnuPG will attempt to decrypt + # message's SESK with a wrong password, see T3795 on dev.gnupg.org + skipgpg = not aead and ((pswdnum > 1) or ((pswdnum > 0) and (keynum > 0))) rnp_encrypt_and_sign_file(src, dst, recipients, passwords, signers, signpswd, aead, cipher, z) # Decrypt file with each of the keys, we have different password for each key + + for pswd in KEYPASS[:keynum]: - gpg_decrypt_file(dst, dec, pswd) - gpg_agent_clear_cache() - remove_files(dec) + if not skipgpg: + gpg_decrypt_file(dst, dec, pswd) + gpg_agent_clear_cache() + remove_files(dec) rnp_decrypt_file(dst, dec, '\n'.join([pswd] * 5)) + remove_files(dec) # GPG decrypts only with first password, see T3795 - if (not aead) and pswdnum: + if skipgpg and pswdnum: gpg_decrypt_file(dst, dec, PASSWORDS[0]) - gpg_agent_clear_cache + gpg_agent_clear_cache() remove_files(dec) # Decrypt file with each of the passwords for pswd in PASSWORDS[:pswdnum]: - if aead: + if not skipgpg: gpg_decrypt_file(dst, dec, pswd) gpg_agent_clear_cache() remove_files(dec) @@ -2197,12 +2821,12 @@ pswd = 'encSpecial1Pass' rnp_genkey_rsa(uid, 1024, pswd) # Encrypt - src = data_path('test_messages') + '/message.txt' + src = data_path(MSG_TXT) dst, dec = reg_workfiles('weird_userids_special_1', '.rnp', '.dec') rnp_encrypt_file_ex(src, dst, [uid], None, None) # Decrypt rnp_decrypt_file(dst, dec, pswd) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) clear_workfiles() def test_encryption_weird_userids_special_2(self): @@ -2212,14 +2836,14 @@ for uid, pswd in zip(USERIDS, KEYPASS): rnp_genkey_rsa(uid, 1024, pswd) # Encrypt to all recipients - src = data_path('test_messages') + '/message.txt' + src = data_path(MSG_TXT) dst, dec = reg_workfiles('weird_userids_special_2', '.rnp', '.dec') rnp_encrypt_file_ex(src, dst, list(map(lambda uid: uid, USERIDS)), None, None) # Decrypt file with each of the passwords for pswd in KEYPASS: multiple_pass_attempts = (pswd + '\n') * len(KEYPASS) rnp_decrypt_file(dst, dec, multiple_pass_attempts) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) remove_files(dec) # Cleanup clear_workfiles() @@ -2245,11 +2869,84 @@ for pswd in KEYPASS: multiple_pass_attempts = (pswd + '\n') * len(KEYPASS) rnp_decrypt_file(dst, dec, multiple_pass_attempts) - compare_files(src, dec, 'rnp decrypted data differs') + compare_files(src, dec, RNP_DATA_DIFFERS) remove_files(dec) # Cleanup clear_workfiles() + def test_encryption_x25519(self): + # Make sure that we support import and decryption using both tweaked and non-tweaked keys + KEY_IMPORT = r'(?s)^.*' \ + r'sec.*255/EdDSA.*3176fc1486aa2528.*' \ + r'uid.*eddsa-25519-non-tweaked.*' \ + r'ssb.*255/ECDH.*950ee0cd34613dba.*$' + BITS_MSG = r'(?s)^.*Warning: bits of 25519 secret key are not tweaked.*$' + + ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path(KEY_25519_NOTWEAK_SEC)]) + self.assertEqual(ret, 0) + self.assertRegex(out, KEY_IMPORT) + ret, _, err = run_proc(RNP, ['--homedir', RNPDIR, '-d', data_path(MSG_ES_25519)]) + self.assertEqual(ret, 0) + self.assertRegex(err, BITS_MSG) + self.assertRegex(err, r'(?s)^.*Signature\(s\) verified successfully.*$') + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', 'eddsa-25519-non-tweaked', '--force']) + self.assertEqual(ret, 0) + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_edge_cases/key-25519-tweaked-sec.asc')]) + self.assertEqual(ret, 0) + self.assertRegex(out, KEY_IMPORT) + ret, _, err = run_proc(RNP, ['--homedir', RNPDIR, '-d', data_path(MSG_ES_25519)]) + self.assertEqual(ret, 0) + self.assertNotRegex(err, BITS_MSG) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--remove-key', 'eddsa-25519-non-tweaked', '--force']) + self.assertEqual(ret, 0) + # Due to issue in GnuPG it reports successfull import of non-tweaked secret key in batch mode + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', data_path(KEY_25519_NOTWEAK_SEC)]) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '-d', data_path(MSG_ES_25519)]) + self.assertNotEqual(ret, 0) + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--yes', '--delete-secret-key', 'dde0ee539c017d2bd3f604a53176fc1486aa2528']) + self.assertEqual(ret, 0) + # Make sure GPG imports tweaked key and successfully decrypts message + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', data_path('test_key_edge_cases/key-25519-tweaked-sec.asc')]) + self.assertEqual(ret, 0) + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '-d', data_path(MSG_ES_25519)]) + self.assertEqual(ret, 0) + # Generate + pipe = pswd_pipe(PASSWORD) + ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', + 'eddsa_25519', '--generate-key', '--expert'], '22\n') + os.close(pipe) + self.assertEqual(ret, 0) + # Export + ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--export', '--secret', 'eddsa_25519']) + self.assertEqual(ret, 0) + # Import key with GPG + ret, out, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import'], out) + self.assertEqual(ret, 0) + src, dst, dec = reg_workfiles('cleartext', '.txt', '.rnp', '.dec') + # Generate random file of required size + random_text(src, 1000) + # Encrypt and sign with RNP + ret, out, _ = run_proc(RNP, ['--homedir', RNPDIR, '-es', '-r', 'eddsa_25519', '-u', + 'eddsa_25519', '--password', PASSWORD, src, '--output', dst, '--armor']) + # Decrypt and verify with RNP + rnp_decrypt_file(dst, dec, 'password') + self.assertEqual(file_text(src), file_text(dec)) + remove_files(dec) + # Decrypt and verify with GPG + gpg_decrypt_file(dst, dec, 'password') + self.assertEqual(file_text(src), file_text(dec)) + remove_files(dst, dec) + # Encrypt and sign with GnuPG + ret, _, _ = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--always-trust', '-r', 'eddsa_25519', + '-u', 'eddsa_25519', '--output', dst, '-es', src]) + self.assertEqual(ret, 0) + # Decrypt and verify with RNP + rnp_decrypt_file(dst, dec, 'password') + self.assertEqual(file_text(src), file_text(dec)) + # Cleanup + clear_workfiles() + class Compression(unittest.TestCase): @classmethod def setUpClass(cls): @@ -2267,17 +2964,16 @@ clear_workfiles() def test_rnp_compression(self): - levels = [None, 0, 2, 4, 6, 9] - algosrnp = [None, 'zip', 'zlib', 'bzip2'] - sizes = [20, 1000, 5000, 20000, 150000, 1000000] - - for size in sizes: - for algo in [0, 1, 2]: - for level in levels: - z = [algosrnp[algo], level] - gpg_to_rnp_encryption(size, None, z) - file_encryption_rnp_to_gpg(size, z) - rnp_signing_gpg_to_rnp(size, z) + runs = 30 + levels = list_upto([None, 0, 2, 4, 6, 9], runs) + algosrnp = list_upto([None, 'zip', 'zlib', 'bzip2'], runs) + sizes = list_upto([20, 1000, 5000, 15000, 250000], runs) + + for level, algo, size in zip(levels, algosrnp, sizes): + z = [algo, level] + gpg_to_rnp_encryption(size, None, z) + file_encryption_rnp_to_gpg(size, z) + rnp_signing_gpg_to_rnp(size, z) class SignDefault(unittest.TestCase): ''' @@ -2328,7 +3024,7 @@ gpg_import_pubring() gpg_import_secring() - src, dst, sig, ver = reg_workfiles('cleartext', '.txt', '.rnp', '.txt.sig', '.ver') + src, dst, sig, ver = reg_workfiles('cleartext', '.txt', '.rnp', EXT_SIG, '.ver') # Generate random file of required size random_text(src, 128000) @@ -2368,7 +3064,7 @@ gpg_import_pubring() gpg_import_secring() - src, dst, sig, ver = reg_workfiles('cleartext', '.txt', '.rnp', '.txt.sig', '.ver') + src, dst, sig, ver = reg_workfiles('cleartext', '.txt', '.rnp', EXT_SIG, '.ver') # Generate random file of required size random_text(src, 128000) @@ -2396,11 +3092,10 @@ class Encrypt(unittest.TestCase, TestIdMixin, KeyLocationChooserMixin): - def _encrypt_decrypt(self, e1, e2): - key_id = "".join(self.id().split('.')[1:3]) - keyfile, input, enc_out, dec_out = reg_workfiles(self.test_id, '.gpg', + def _encrypt_decrypt(self, e1, e2, failenc = False, faildec = False): + keyfile, src, enc_out, dec_out = reg_workfiles(self.test_id, '.gpg', '.in', '.enc', '.dec') - random_text(input, 0x1337) + random_text(src, 0x1337) if not self.operation_key_location and not self.operation_key_gencmd: raise RuntimeError("key not found") @@ -2413,15 +3108,15 @@ self.assertTrue(e1.export_key(keyfile, False)) self.assertTrue(e2.import_key(keyfile)) - self.assertTrue(e2.encrypt(e1.userid, enc_out, input)) - self.assertTrue(e1.decrypt(dec_out, enc_out)) + self.assertEqual(e2.encrypt(e1.userid, enc_out, src), not failenc) + self.assertEqual(e1.decrypt(dec_out, enc_out), not faildec) clear_workfiles() def setUp(self): self.rnp = Rnp(RNPDIR, RNP, RNPK) self.gpg = GnuPG(GPGHOME, GPG) self.rnp.password = self.gpg.password = PASSWORD - self.rnp.userid = self.gpg.userid = self.test_id+'@example.com' + self.rnp.userid = self.gpg.userid = self.test_id + AT_EXAMPLE @classmethod def tearDownClass(cls): @@ -2438,7 +3133,7 @@ Subkey-Usage: encrypt Name-Real: Test Testovich Expire-Date: 1y - Preferences: twofish sha256 sha384 sha512 sha1 zlib + Preferences: aes256 sha256 sha384 sha512 sha1 zlib Name-Email: {2} """ @@ -2451,13 +3146,14 @@ def do_test_encrypt(self, sign_key_size, enc_key_size): pfx = EncryptElgamal.key_pfx(sign_key_size, enc_key_size) self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True))) - self.rnp.userid = self.gpg.userid = pfx+"@example.com" - self._encrypt_decrypt(self.gpg, self.rnp) + self.rnp.userid = self.gpg.userid = pfx + AT_EXAMPLE + # DSA 1024 key uses SHA-1 as hash so verification would fail + self._encrypt_decrypt(self.gpg, self.rnp, sign_key_size <= 1024, sign_key_size <= 1024) def do_test_decrypt(self, sign_key_size, enc_key_size): pfx = EncryptElgamal.key_pfx(sign_key_size, enc_key_size) self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True))) - self.rnp.userid = self.gpg.userid = pfx+"@example.com" + self.rnp.userid = self.gpg.userid = pfx + AT_EXAMPLE self._encrypt_decrypt(self.rnp, self.gpg) def test_encrypt_P1024_1024(self): self.do_test_encrypt(1024, 1024) @@ -2471,6 +3167,12 @@ def test_generate_elgamal_key1024_in_gpg_and_encrypt(self): cmd = EncryptElgamal.GPG_GENERATE_DSA_ELGAMAL_PATTERN.format(1024, 1024, self.gpg.userid) self.operation_key_gencmd = cmd + # Will fail since 1024-bit DSA key uses SHA-1 as hash. + self._encrypt_decrypt(self.gpg, self.rnp, True, True) + + def test_generate_elgamal_key1536_in_gpg_and_encrypt(self): + cmd = EncryptElgamal.GPG_GENERATE_DSA_ELGAMAL_PATTERN.format(1536, 1536, self.gpg.userid) + self.operation_key_gencmd = cmd self._encrypt_decrypt(self.gpg, self.rnp) def test_generate_elgamal_key1024_in_rnp_and_decrypt(self): @@ -2490,7 +3192,7 @@ Subkey-Curve: {0} Name-Real: Test Testovich Expire-Date: 1y - Preferences: twofish sha256 sha384 sha512 sha1 zlib + Preferences: aes256 sha256 sha384 sha512 sha1 zlib Name-Email: {1}""" RNP_GENERATE_ECDH_ECDSA_PATTERN = "19\n{0}\n" @@ -2525,7 +3227,7 @@ class Sign(unittest.TestCase, TestIdMixin, KeyLocationChooserMixin): SIZES = [20, 1000, 5000, 20000, 150000, 1000000] - def _sign_verify(self, e1, e2): + def _sign_verify(self, e1, e2, failsign = False, failver = False): ''' Helper function for Sign verification 1. e1 creates/loads key @@ -2536,8 +3238,8 @@ eX == entityX ''' - keyfile, input, output = reg_workfiles(self.test_id, '.gpg', '.in', '.out') - random_text(input, 0x1337) + keyfile, src, output = reg_workfiles(self.test_id, '.gpg', '.in', '.out') + random_text(src, 0x1337) if not self.operation_key_location and not self.operation_key_gencmd: print(self.operation_key_gencmd) @@ -2550,15 +3252,15 @@ self.assertTrue(e1.generate_key_batch(self.operation_key_gencmd)) self.assertTrue(e1.export_key(keyfile, False)) self.assertTrue(e2.import_key(keyfile)) - self.assertTrue(e1.sign(output, input)) - self.assertTrue(e2.verify(output)) + self.assertEqual(e1.sign(output, src), not failsign) + self.assertEqual(e2.verify(output), not failver) clear_workfiles() def setUp(self): self.rnp = Rnp(RNPDIR, RNP, RNPK) self.gpg = GnuPG(GPGHOME, GPG) self.rnp.password = self.gpg.password = PASSWORD - self.rnp.userid = self.gpg.userid = self.test_id+'@example.com' + self.rnp.userid = self.gpg.userid = self.test_id + AT_EXAMPLE @classmethod def tearDownClass(cls): @@ -2641,14 +3343,16 @@ def do_test_sign(self, p_size): pfx = SignDSA.key_pfx(p_size) self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True))) - self.rnp.userid = self.gpg.userid = pfx+"@example.com" - self._sign_verify(self.rnp, self.gpg) + self.rnp.userid = self.gpg.userid = pfx + AT_EXAMPLE + # DSA 1024-bit key uses SHA-1 so verification would fail + self._sign_verify(self.rnp, self.gpg, p_size <= 1024, p_size <= 1024) def do_test_verify(self, p_size): pfx = SignDSA.key_pfx(p_size) self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True))) - self.rnp.userid = self.gpg.userid = pfx+"@example.com" - self._sign_verify(self.gpg, self.rnp) + self.rnp.userid = self.gpg.userid = pfx + AT_EXAMPLE + # DSA 1024-bit key uses SHA-1 so verification would fail + self._sign_verify(self.gpg, self.rnp, False, p_size <= 1024) def test_sign_P1024_Q160(self): self.do_test_sign(1024) def test_sign_P2048_Q256(self): self.do_test_sign(2048) @@ -2700,14 +3404,14 @@ def do_encrypt_verify(self, key_size): pfx = EncryptSignRSA.key_pfx(key_size) self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True))) - self.rnp.userid = self.gpg.userid = pfx+"@example.com" + self.rnp.userid = self.gpg.userid = pfx + AT_EXAMPLE self._encrypt_decrypt(self.gpg, self.rnp) self._sign_verify(self.gpg, self.rnp) def do_rnp_decrypt_sign(self, key_size): pfx = EncryptSignRSA.key_pfx(key_size) self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True))) - self.rnp.userid = self.gpg.userid = pfx+"@example.com" + self.rnp.userid = self.gpg.userid = pfx + AT_EXAMPLE self._encrypt_decrypt(self.rnp, self.gpg) self._sign_verify(self.rnp, self.gpg) @@ -2719,6 +3423,13 @@ def test_rnp_decrypt_sign_2048(self): self.do_rnp_decrypt_sign(2048) def test_rnp_decrypt_sign_4096(self): self.do_rnp_decrypt_sign(4096) + def setUp(self): + Encrypt.setUp(self) + + @classmethod + def tearDownClass(cls): + Encrypt.tearDownClass() + def test_suites(tests): if hasattr(tests, '__iter__'): for x in tests: @@ -2765,5 +3476,5 @@ else: shutil.rmtree(RNPDIR) shutil.rmtree(GPGDIR) - except: + except Exception: pass diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/CMakeLists.txt thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/CMakeLists.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/CMakeLists.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/CMakeLists.txt 2022-04-15 07:49:22.000000000 +0000 @@ -62,8 +62,13 @@ endif() find_package(JSON-C 0.11 REQUIRED) -# We do not link against Botan, but need headers. -find_package(Botan2 2.14.0 REQUIRED) +if (CRYPTO_BACKEND STREQUAL "botan") + find_package(Botan2 2.14.0 REQUIRED) +endif() +if (CRYPTO_BACKEND STREQUAL "openssl") + find_package(OpenSSL 1.1.1 REQUIRED) +endif() + add_executable(rnp_tests ../rnp/rnpcfg.cpp ../rnp/fficli.cpp @@ -75,9 +80,12 @@ ../fuzzing/keyring_g10.cpp ../fuzzing/keyring_kbx.c ../fuzzing/keyimport.c + ../fuzzing/sigimport.c ../fuzzing/dump.c ../fuzzing/verify_detached.c + ../fuzzing/verify.c cipher.cpp + cipher_cxx.cpp cli.cpp exportkey.cpp ffi.cpp @@ -103,12 +111,12 @@ partial-length.cpp pipe.cpp rnp_tests.cpp + rng-randomness.cpp s2k-iterations.cpp streams.cpp support.cpp user-prefs.cpp utils-hex2bin.cpp - utils-list.cpp utils-rnpcfg.cpp issues/1030.cpp issues/1115.cpp @@ -118,8 +126,10 @@ fuzz_keyring_g10.cpp fuzz_keyring_kbx.cpp fuzz_keyimport.cpp + fuzz_sigimport.cpp fuzz_dump.cpp fuzz_verify_detached.cpp + fuzz_verify.cpp ) if(MSVC) find_package(WindowsSDK) @@ -162,7 +172,10 @@ JSON-C::JSON-C ${GTestMain} ) -if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +if (CRYPTO_BACKEND STREQUAL "openssl") + target_link_libraries(rnp_tests PRIVATE OpenSSL::Crypto) +endif() +if (WIN32 AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) target_link_libraries(rnp_tests PRIVATE regex) elseif(MSVC) add_compile_definitions(RNP_USE_STD_REGEX) @@ -187,7 +200,7 @@ if (DEFINED ENV{RUBY_RNP_INSTALL}) set(_sourcedir "$ENV{RUBY_RNP_INSTALL}") endif() - set(_ruby_rnp_ver "master") + set(_ruby_rnp_ver "main") if (DEFINED ENV{RUBY_RNP_VERSION}) set(_ruby_rnp_ver "$ENV{RUBY_RNP_VERSION}") endif() Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,28 +1,28 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQHpBFqb+uMRBACWhHfRWXnNIJAjdsSHyYU7KKZsJF9vIJAMlaUZETuVeM0aqmsc -nAOW5BnntMSCz5BBiwNhn8pnc1Btts1VXOvq+ns3doPXh/dVgl4/gUe2TZHxA+AT -kwDAFIKv7kOn70pAJ3Mleatnc51xJjHlxGdSfNlncWwqqR3xSxL4ZWeRqwCgzj4t -1HdIErnJtQwwPSgxfMdgtHsD/3kZXGcVF9PDpQ8XAq0oxZ0lr1atnLbzCCkAfTJ0 -/DEUy8kjrZ3czZn4bsL2Jad1QdUX35fH1QEixQwFVqG6R1vI5LtIVKgWx7SaNLJQ -TWQWyIRwYG1kOmqlmcC+d5yy8LVf5fkuHLKOq2ls57PIOQ/IHFegAcqhx4bsr+c7 -gBT/A/0YppE37eSgthoPC8USy/lhgXAOxXtTcnP8cDDCVRuwWMsJGpaOqbbPCYLo -fWU0asMoBJ1OMg2tnpgBDBdylIPL8uh4b5HsiJzmgQbKdrdP97s9MbRZVFDfXTyv -0HkAlV0f2WJwUy24avdDnxSyV/xmrJ4uIwsRctLEz4WmSReyzf4HAwLX40KNaOtM -b+9QcG8H67qqjWwNRHZAX76he2YJ3GRdILncuHhjGPyRNt6Ieevlbu3D0uHVWWWu -e8+Vk6riS6/Rhk2dtDhUZXN0IFRlc3RvdmljaCA8R251UEdfZHNhX2VsZ2FtYWxf -MTAyNF8xMDI0QGV4YW1wbGUuY29tPohyBBMRAgAyAhsDAgsKBRUICQoCAhYCAh4B -AheAFiEEZXgzG/iSHPTfmEM5DqpP2mZGXHUFAlyH46QACgkQDqpP2mZGXHV6WACg -tsWofgWqkal5XxXLS9ibxiIYjFsAn2jv5tu93CarOxixNeaZIM0hRh95nQFgBFqb -+uMQBADPQ98QmgoeMYiOD3/X+Z3EDQXC1k33sE+BZpYySDU5ael/8lHivbg2khE4 -f5m623lDcmCqKHhRkMDMJyLiKszvxm6HoDPoyRFkoogifKJ36hNjGZu59ZmsKKUw -FmD7+/MGhpFQ63lKuNARuu5EDaWQ53X0OXOcGcsN+1DwyXryqwADBgP+K8vvSa6j -CZZZTb/RQPufsxyvRBiNwRIA44Ghr17J9UakfJyhjMAwirjj2EBeEwph2+ZPFZb6 -vyQNEdm+x8DIuiGFAOU0b8H2+NrRBqKb2lZBeiy/0e6lpNlw/fTeEWSMMzsigONd -YArxS1k2bD/mEBFejdnOih45VuvuHJ4uhNX+BwMCZ6XPeqiZ1UHvnDLsxzJxCmL0 -aKJUuzaoaORLSLJJqkXEu8BBH3a1CFAdg6etM3feH37bfq3B3aLut4Zkl6OQiUjk -4fBjUOvvL04buRRz5ohgBBgRAgAgAhsMFiEEZXgzG/iSHPTfmEM5DqpP2mZGXHUF -AlyH46QACgkQDqpP2mZGXHVEPwCfXIRk+TRjdf7TMHiAJnpe4Vothp4AoL0LBeMi -LYDddHTu1aFOM0Z5qP/g -=0F1I +lQHpBGFe77URBADp3o2K++kVaHiAHBoSZvNPOYBtJIEFN8wWzDUkOa5CDKAyzj8X +T70444ePqvloTHMbNfM3EF7Qe0sZDEbVLHJqsOFQwUF7JeHlBQL7H2w/W90tIf4f +kyaqYO4uK2YvW7y5UpqfiET2hukoLq404s16znkeVKHZ5zsvGqBYkzV2jwCg20CG +UHyy/TrR1EmOeNzQDbbkU+UEANb0v/MFMkP7M9ZFgR3wQL2CUvSzN7OOME8ifMFS +y22QQq7latxbeuUDjDjGNhXGtSIUmgHCwc6nzHvNpQ+cm/NWrZvyOv3pLOHkU1tI +/0esSCIw7egwApygCoBgUH27w8lFjBWOXNY10kCOyzTVXYeLcyCYOq8+Bh9KmMOb +xj6qA/oCggr9jYCjBgbrm1m3iuOd9vttqfTb0Ab13l3UKQI1px+jX42AIALSa5uH +iYbEk4nYVLgBTNFY8bI3BMKESQVMJeS3oXyRAxTAsWvD98qXV0DR15wH2Rq2HHNa +wmltcovRrpzfsCaFKr50HVBC9mVeECg2o66sbcjkGQx6L6Te5/4HAwJFb51WJw6M +svM/C8nNxRC/zFiXH9ACYyvnDRBO+mctMbvf9euTeCMk7zffR9oMtd7hUOTeFeyd +LCltvoxeiBcuefCWtDhUZXN0IFRlc3RvdmljaCA8R251UEdfZHNhX2VsZ2FtYWxf +MTAyNF8xMDI0QGV4YW1wbGUuY29tPohyBBMRAgAyFiEE11CMZvArgEeh6W0AlOdk +hnqNnMEFAmFe77UCGwMCCwkFFQgJCgICFgICHgUCF4AACgkQlOdkhnqNnMEsGACg +hYrQ4OqnJupTXd82lNb8Bq5I678An2r6SmdeVn9Z/skLDVn4coGaw83UnQFfBGFe +77UQBADwCH6poAGVGQl2RPG44jIH4G9FT+zHwfgi59sc/g7xKNIROLy3SmXp0KNb +9I9OebQPPWVost/wW5rHlMKT9ecnHmsS6N8+kFvu+zp19Q+OKkp9ybg6kagjj1tW +H0ONGwGOP7qjSb71XG/YtUZlQ6qfjmTdIvpB9DymsM7SLXQckwADBQP+MHWOFQmN +YSdJq0bZPtQbC+SbXtuiyqAmp/8/0OTW4ZTGiDCzjC9AWl5gV1SX7zKiN5+HLWI2 +wfXKEqWQnto31PP0Bs1X9c/3hdL+6ylbnc4IuIScNuQN4E7KtLKtjhSKdhKlvDZR +eZSkRfz74efmf5+nzgbI2XMjfRKRZdOVwgH+BwMCP2K49baJwJjz1WsGK3uY53+4 +WYCwmluNNpkDzMCpNkxM7ACQ4EWvBayu2UzSrgK95fK+g/gRU6vASUnuiItLK2sn +Ve0CqdP/PUYbpDWfiGAEGBECACAWIQTXUIxm8CuAR6HpbQCU52SGeo2cwQUCYV7v +tQIbDAAKCRCU52SGeo2cwTORAJ9dUmdbapJCw8DJPKo3zrj5K2uXPwCbBAEh7kdn +MZK669R2Snwp1hYOINU= +=sBQ1 -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,33 +1,33 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQHpBFqb+u8RBACEkHgNT8H6RJOamslE09cz9TWP83a46sIrZQ+IHxsTNkPHKUpi -9t5hv4e2UIDVaw6gjSToWccp+HZGHECoVo+Cpp816cfWbGDP+siuZvTQfBh3DuXO -LX/Xj3oh1BkhvTsW4uCuK/8bZnEubwu76zzFzWVTQHbtiQ6o9opzR8de0wCg8/Dh -3IZ74Qsx+IokIVJSXaO5jPsD/3EN0a38rxaLh7NtGeK/OW1x+8DycCzRcAcsaADi -KuhXR9D+Tuu7NXbYNlgbizS1oreBA7AQjC9Qj0Zpl5FgOExDJkYFfdfWy42sV5iN -Ho8CdZoJb47pFNwGFKTFo9mDDSsTwmksGhWLaJmnEasf4Hg52g+sI5IMbSGzVeMj -rOl3A/9IojmQknty4+mlvaZ+huA48xlUiUpbGiVwiCNbdB/b116XGx3kLg8ZtNdu -L+RDA9EK5ZglOcgk5GPmRHiSF5TxEktIHOdMW0CMJmafvrSOzSk64pX6RICHPGVp -OPchF6d0lPYYYJSb2SPC90JvEEODFk0W2YzKkxD0jC4Suzf9HP4HAwLe7EwZ6ihN -LO9oR6qwLiP+tcULd3+en06TxoeFvj+LndKT59w5L+trfKPJFFMTGzwiFL7R20U5 -o/BNbifpdJyK3aAFtDhUZXN0IFRlc3RvdmljaCA8R251UEdfZHNhX2VsZ2FtYWxf -MTAyNF8yMDQ4QGV4YW1wbGUuY29tPohyBBMRAgAyAhsDAgsKBRUICQoCAhYCAh4B -AheAFiEEju+/XRTfVTycg71DIejIVoBSWlUFAlyH46UACgkQIejIVoBSWlVzCACg -zHnLLsgt3AONW4SeFVlkDQx4vUwAn3DBoiRPGkdfLPlOE189oVVzu7XgnQJrBFqb -+u8QCACMrtAPshO/DCKmTwyile9b3EchMFYIGFw29qmIVn04w33lNggMVALmbuTK -GOfb5YpWnha6D4hiYVG3hgCWM7xMcvqgk8meivfSeC6swrp8pX6C/X+oHtYKuACJ -kft13TO2kBtx6tzUHVGeJ0kp/NqoqIrMt72f4EpSBx88q6UkJ6ewWVm/wh59vrQM -JuxTaeHK2dJ0NqYh5VdGoXosFraOMBeQkrzwAt20UumjuWs7rL8tDZl/PnaO3Gwe -QY2tacZgbXIRTkdllbHksuA21ySUr/mqN1JlgBk14lYh6aO4xE9WTtbZWhN3jwaB -hYyafvd/im+cgwWnBc4PW3qdsMeHAAMFB/9fRg1lfbyEtu4ygBbYBoWHL1XF2OLT -FpG9Igv1Dhk8ZNV2h0QeQrlPPHOyRBU7SES9Qe3w0rCFiAmUQufG6dN3pGHrPWJd -qGCW8NKIs8Bh3YPsnoCvbC7Y6Z/CwIBrvNZaljOxGmibrTubrG3E+a8AG83iYG7D -BSifHOEzv9yKdN1nP6NZExeEyyjxNZvIO1KVcUlCO/lJVdtC3fA4Rvv373z/+/Z8 -2ls7WCZX3w6gS4B1ulih3H8zYQNbmdjJbKZtAFNg+GgrTmI0q/4VC/lDNhlEU8mE -oZO8dFRx/w6D4PGjnn5uVqZpPsC+Q6xgJqEQ5upxxcsgJ3YIyMMliAMe/gcDAks8 -Lrkvzxn672R1AGVhQoNMfOuWjyA6Okaphhd3cpAL0miycKso99yA/3UdmigeacDB -nRDZu/02fC/CNJBU3ljoNVPz5eCjrNmBnXXdEY3pmyzfB12ghoKyLIhgBBgRAgAg -AhsMFiEEju+/XRTfVTycg71DIejIVoBSWlUFAlyH46UACgkQIejIVoBSWlXWmQCg -8JQL69dtkOOZkEgOzovCacMz9gkAnR08BJLuzmnpKrYd0Oq/pCsRR6qq -=zb1I +lQHpBGFe77YRBAC7YuR+mUtDv8tgj+xheX0e1hTpnevRmA3yGb1EOYHEucfOk0k/ +KjFFHzouUP8eLS6CCiKq0PAWCNuHrgTxxSGURWVTic3/vMpjWiPcSqxsB5YkvqCT +rdM+CgzsEL22FglNd/yL/3EYuvO1UGF9TtIhOs/92AG/x5/pJyJKehr+GwCgs0Zi +Aa2J/FmhsvmMWFD8WlK6cJ0D/0X07TPbJW3PXGbovnBc/F5k8tcfLOyYuj1Pv/nW +DUFuovJt88GoUd3lDTdO51NUK+La32hMLnvIgagEjr1wBzfMsbSmmkfEwRXWQLMn +Lp9XPkEaVvAovW7xUleF1SL1bSrRRnmWjmc+sylR0I7nlhNLqbjoYBb/IaVyU2jc +zhk1A/93rntBVw5DXZuOspx+800UfIn/IQnjMYUYMywa3C2NjZvZL7yGVbn2tUFz +xBSQxaj3gvjzYPI5z1VP3hLY/99zQjzksNjdQDn+HuKWb+4rtW0TzE6G2yEkclJK +IxnK8Rw4pNAYEaZCDyf8L3FCd2ts7v2yU1IHYEJW8ibhN+D18v4HAwKqm9e9T2qs +5fPlJ2vhBUVfKyl93F4+aY/jZFF8laKLDPbVSwwfMhjM+MqewiknxGp1k/5Df2Wl +XM83Xob7T5Dx8KJTtDhUZXN0IFRlc3RvdmljaCA8R251UEdfZHNhX2VsZ2FtYWxf +MTAyNF8yMDQ4QGV4YW1wbGUuY29tPohyBBMRAgAyFiEEzCEZP/BL1q3fLdXBm00p +ZANQVKUFAmFe77YCGwMCCwkFFQgJCgICFgICHgUCF4AACgkQm00pZANQVKVrgQCg +nvFdnU1/NeKhVI/+tw6b2vloyt8AnjWYdVSGjHT/zd8jYBlMbMf0tyOnnQJrBGFe +77YQCAC+5tS9jY7IEv62gjNmOvruZL8wb6xEZ7/6F4K/IQfKNexOP/xPPOYXsNbS +GE/FBHLt808Owpkp56wtu7y5uI4yAA8wB5WnIlFeVurijUNiHcg4VNVf7aObyTqA +uJWiEQBXlDQHbKQJ9WyMAubzdsvRK1kHlW0ZavCAu3dQ9SG2JEaDP5ijr9yWM8Bp +Y+hdbzta17/5+w/N1Eve2haWwzdi7VA9S8670HetBZ6BMUcCERHYGkZ9qdauvunc +CDl0oMsaZedwofuftI54AJwVnBcyaYWB1C4xVGLucLDpLM39rRV/1HCzS/FeBXNE +SjZBpY7Dgk+P862A/C5qH+1P/BZnAAQLB/4wv5MPzjuevr5rUgoxz7plrc9aVcgR +CPdBN0NadiFKqYbxI0wxRbMMjc+dX2dSd671z8Dn6pMrdriDaWuuwxSdXmMCElmK +IBfpUZx1L36gOgZbw2utG/A412cLa5J7lyzyluN3Gc1qnXu7f6PYwHQkb6DlcOAX +ORpByOOio1M0TiidGdN6jcZIvOSrZrXX1d6IPfbO5gqp3F4orNHleG1QaYXZrJJS +WMq9PmFrvgzlcPp9FJXh7Yji6ca44oyJaSpAJrsVowV2dmcWohtpzYve6JGrmsCK +cGhlo8CHuUIG4bHKYeH7++gBJxJZRBrKiYkgZa+vcSJdf82BPIJBFzk9/gcDAoFW +HN4aiWy986alVKUOHUpmoPmqUunVyhrjRj8JF1ul5k52/NjsnjW4pufKdkJ1CqVQ +7xNbAC9mTHk9Kn8LkJdTI8sULUBJYARmrKX8ez8QNjJaZSCKYpX3A4hgBBgRAgAg +FiEEzCEZP/BL1q3fLdXBm00pZANQVKUFAmFe77YCGwwACgkQm00pZANQVKWDAQCf +U/uklCOD9vcVLVp9fkA7lOpky04AnipIycqWKmIY3LuHahP1AFP0uNjE +=lQoQ -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,32 +1,32 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQJZBFqoRiQRBQCXibh9+/DmMcyIhF7NuOF84HnRg9TNbk8K2OT9/AmksBIMQIEm -M/rGQEUle6Px7lDYM6PsmQNK42tWy1y8VhTZqbSXuWVpYtYaVOuzIO3ReNJsS6eg -uRIxJVb9bMa2/+B1fI7iE33roBkPrRATYgjH1LYL50i+ntMydn79GonI5d+QqnhT -A/0X1lIoogpwKWHvTnHWaSyWUvWatHpX5vNvAODGOv36QGkMOlXRsygqKlBdJP+T -/hgz/TfhXP4FBQCTM1wPLh4dEDhaC0SbHd9nF/tZuoEl4+KPKLlt/oIb3NSoQWyy -Q1+h4Sui43ZzNioM6NehkkmsMwm/dLdUZZuhga2VyQmqRlxnwII7o9Dqjh+QBHv9 -m4JICczepUyAxqvLwrTeqWUU9qfJcbxIAcic2l6jKdNGpOfHwLOLRGLUkj42qvcR -jGF9i24IBEPDHmWMqkkVSNYnsR565PfnrptoBP4xYOB/F5NAjlHJl4HLkbxzXYpT -9WWf72IYI+br899ttCIul7z/Bq4cdP4lHVpf0J9xEd/AryHe09yCZxz0ugu9fvrN -X+Dr5DoVXSE9nOUllA4GrmDslnkTQeEuLqrw3UvQnCOak7W91jkD/Df08dkGrZzS -AVizoEMwxCAmzQtJA/3gzbzKIiB4XhCmMezLRoN/qeP1DfP4Umexeb8iMqN8/gcD -AiZ9OszmSZ/u7ouo/bX5jUNyAHAry9QiAYm0hZsITwMDzPW5cvEWD9fgm+SlTuJK -8lKNI+bLhEMK+nkwW4ucNFRgJ2kHHeOHLGntpbQ4VGVzdCBUZXN0b3ZpY2ggPEdu -dVBHX2RzYV9lbGdhbWFsXzEyMzRfMTIzNEBleGFtcGxlLmNvbT6IggQTEQsAMgIb -AwILCgUVCAkKAgIWAgIeAQIXgBYhBF8lMtQ7trc8kQZCYJZz4UnJEv/HBQJch+On -AAoJEJZz4UnJEv/HixcA31Jta5UpkkljhH/XDk7yklVZMw3d2NPKVquWeRkA32Vh -lS9B9sdCjugkkbVQ+o/PdYsuOcdMX60AN3WdAZsEWqhGJBAE4LTfcLJWW0hv93XC -4gHO+kMR4KVN0Uga/f/mA+udsVb8vUMijyTDWwcepdcasVbnXvOEuB7bnSXMj/Y+ -2y2gqDaoXFeRdASakTfIrAUiDXOVRTQAUeMAtaqkT2Qr86uQT698JFoXq6xtoctV -dUQVcKZJaXXc9c6jEOlCuZyt9QrJVeG2n5OVorRJPYbZ4akipYbrPJ9HRv6m04ue -UwADBgTeJ15ym6w0EvG6dQYrpaLtnpeW/fsZoUKkbrUw2ayU0AsImUoLNGgeu5mR -Mdg9tVfXDgUcaMDs6GNRAnU05Jdh6hewa8+xavibcoR+PZ5rZo5p8cvXTkkoj+63 -D94/egCrNtPS0ktflmasiQaFEV3RPuIrrLghYpi9pRF5d7uuBxDzdKPU0Pfz9mG2 -SphwM3ooOP4dn/RbH3pPXDCZ/gcDAqKgrdR/IW/Z7sNkfoQH/GLZaX0lW1Gu56OT -uOBWnd+IOWxlqGljkNEYYPkob0+SKjE99bA2tGbUpNgmkugFvhs3LY57JWu8b74P -6nGeNwRTzhGIcAQYEQsAIAIbDBYhBF8lMtQ7trc8kQZCYJZz4UnJEv/HBQJch+On -AAoJEJZz4UnJEv/HzD4A4LdWixgRy7sPLqpnjuFYQsGMUxJOpt+ooEIKoGsA2QE8 -UUHxDFYz4q8Fq/KOAwf12mF1xvKKUvyDnMs= -=/qG9 +lQJZBGFe77kRBQDED0dCShzpj1tWOXXig8N6AAaYng6zoXtPOkB0+K+Uq0Qu+OwZ +ZBk8ELDMJgF5gGxGsCKu9ALFeaHubVDkAtWcgj0iq+cZKILmuWW83+HEBCTb1pet +SIYMXFbhGMiJSNlw1Is+OvOiluqB+TKj5ZDF4VWVFxwG92izNRjQMkBNcnTP/ZzF +aJXmjfkakvwzdCqAQyb5RtSZXz/HuUzs4/gfAODuZNFduli0EEgjRxdLQJ8WmSjG +XWmvQgKePq6XBP4+PyS2svI0KECmVTH5nlxFX9Fkfq7TQOrIg8dM2a9qHnFw8eq4 +Ibww71eCPVnsTZo+AEiBE8rfohraHPt1Pc158+MIVgvDCczysmQXB6RDUoV62tWS +zxDIVDmFju5MXDP8+3Nu0ShObwdGjH2XSr4et3cjS5KVIzdoHeV5S1B8qFDCXhn1 +Z3Zs+WuT80ygUqu/SWzSsQtea7oOCQWgcJjBBQCIX6YFAQjC3aSPtEPnyb/xjDQj +Y45wuV71Dv7Wxttwki8gRUahxADDfA8rVxgjDQLfIBfcZSy3RRFAwL/hpLxlb61R +Sf1197ZI1fd3T0AMyjPmOxEzrOu0mKPVxzwplWcOpvEkpPWk4yOMdXq/FmSdL8hX +hX5sQzt01PuTCcTU+Y4B53BrMdqPaxYZYlr+K56e+R6dFN9j3i9/WfyQbnjc/gcD +AmXE+lFwAxT4872MR669qt1ItwzlrwzuAKa/zLpcRK2vlA69oZgDwU7834r2c/LI +WSrIDRxP6A9tub+f5kVJ+S9gwT4Pg3AaLMUAdLQ4VGVzdCBUZXN0b3ZpY2ggPEdu +dVBHX2RzYV9lbGdhbWFsXzEyMzRfMTIzNEBleGFtcGxlLmNvbT6IggQTEQsAMhYh +BPEWW0sV4oPJZ6LLdbW4bfCx3VtoBQJhXu+5AhsDAgsJBRUICQoCAhYCAh4FAheA +AAoJELW4bfCx3Vtoi+IA3jbZGv4V54s0UU3Pc2xqe34W6FKcQ74ylrFYLCQA30Pz +Llno8IO0fMEkjODxpXlfqFnE16Wm9npfs6OdAZsEYV7vuRAE4IvJb4BHL375yZKP +vHTbFcaFuf+ElqN2iXVEZTPj/uop1Gp5JrM3OZDoMa/gTdAXWmk+AWYy3mLfp8dB +n0gHNWyKDEFg8XqGiQSsYDxjkIHyKC/m6S0i+m3EetQwikAt6Uu/iY8HMWQcQ7Kk +n3DFnd6DD0lS+nn2J1y/xYQacPv7i3xhp0+vnTbE6dNerwmNPQfMJPB+FNvf+l0H +LwAECwTggpUOZ79yqWJyoPR5OhdCEjLx9LtJYdzu9asGWLZgztwDKwabqYo/1Qcr +2iPd8rZr1YJrG6L9nfRL+tENO4s1m2P7w/bJ8D/hpVnFSPNXyLRWf2L9+hVtfPKi +hJ2ysokhjUGYBjXjBZSxboHkXYQpb/w1ZJKwhpZl5Sw2XKKrQC+n9LeD77jmSlQr +TNZ86o0xfcGzbWENPLhB875a/gcDAivOpDfD8X+T85Az4N8N01QZoQ0QdX1GSiFV +CRIFWg3FKuoB+5ice2CtdfmKARtGPAnQmclo2uYQDQzEQGlu+J2vWLXQN3M6hIV+ +tQXzn/8ydHyIcAQYEQsAIBYhBPEWW0sV4oPJZ6LLdbW4bfCx3VtoBQJhXu+5AhsM +AAoJELW4bfCx3Vto8FAA4ICXEA1I6ZDZ5AHKDqAsJEDKgEY8taTJa0IbZwEA4Jbg +z+B3rt8NNrHs5AkFBQJptxbIu1gegrJAlPg= +=79Pf -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048-sec.gpg 2022-04-15 07:49:21.000000000 +0000 @@ -1,43 +1,43 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQOBBFqb/CsRCADKhaLd+FKjjQG9S6n1Z28fOne2XhNTcFhlEPDi0xs1QnP9UHuS -9M+BJ5CitIphBGwL2+FPiKhrnXl2CR/U2ADoZgfXG8fZnV31qbEInDwdcXWk2GOe -n5FXNuGf8crwTDnzSFR1gRd6nWhW5KJwnX+vEp51swZ0Yv5ethwAA2mrBR2aJMFK -zPpwiu1u6bI1xnFfDWd5jDtrvQ+R7Hxr48wlh9tpZiQj87bysWaOhwY8ImopxV1l -nsN7SRuzlCCoVxw1kZrTmOndffuvLDdcJuCbCeO4EstCoFWcNmJfEaJklQVhv5zV -f40FgVAYOmrQJpAshaojSC6r63QqKVPO/vrPAQCpn80QyAeouoDjhrxE1OrcM8P+ -g6Jcb1zFUGKqBZga+wf/TuL+C73PslPAyxwSpVffzSJqkcdOPEDSAcnU/gIEeBQ4 -n2Cr6iiR29muMLeNpix0Ki/UQdvkOwzluoMOLzscoBM4EPCwIuJ36kU9FqsDF2Q8 -B6Vv0UJ9/rdG11aHjGMs+b8YZCxTiURSybq6VZ+om7bbrNRLOL1picCX/JVpANf8 -rHQb+GwIv/OdDwWLbGp9l2QvvaYxpLjFK5CzJbe8WlrHBhk8FTCVNA4/abRD6v7H -zL5w7UwuRG9CzBmu54x931PH6cnsKiFb/btnrIRy3HYfzUAWjgyftT+xsvCUro04 -hhtaZeOwSf+S06Kk7bzGDm96IQ+pLLB70+/TnpDtGwgAr3lwAEzbs9oWqaAcP7Ev -YrxlBWsJxiN8rhiuMwzy632RMqqRAMxsgJEp6pDCYd++m6YiitZ3ORePQVkdn7TY -fLXqpAb932TnTUQHIEqefku8t5I3p56Kj4yh5c9Oi6TCiqKF08dCHLxeXlffMvHh -kzq4o+3tW6spAObzPewykJ3CoOzQyfzfFuAHbhGPSXlKe59TRmV+FVyoNH5kRJti -8y6k8WPoZSGZEIZqaKrthAKhYX2YtvZR3QP+3ZEGoJDcjf4nLUvvaS1JqyTfQ+Pn -BC5I4JIh0uPw7suY7dFYuB3s/QwIXkE9mP72iQCS/OhOUH7XhrehrRnvJFh1099C -6f4HAwIeStRwsuQPF+7aM9hlBRH0Pnq184CrG6Pj/8r1pO6kQFgYFk+pgdEYRAwM -ziFhL40gSNHVkr9/XQ6PaLdsd4MpcxkRyoJlrLKiRoj6xoWitDhUZXN0IFRlc3Rv +lQOBBGFe77oRCACu0ffZDrfcFgJzr/JAyiFQkfPGVm89BzyfaKsbHzAiINDCu+/t +R2YYMAZAQ1/d9/MOWYASBTHePDZ924cn+ctcAZugavhsMRh5aDbGsbLk2qY/Mw5D +9BtMzOUHIHd7HWn/kgs9Vx1ueZtPPMsboL6kK04IVzTgoAGbIYye/imtwiWJZl9a +/WrMMgWuh/6baQFMsRptsMqObNw6OSwgVGn7ims95daQsHXgbvwUJlVdgnJGBc5X +pAH9JSlGItLrTNCs/5pLcs8hJMTVV3efn22aBFERUzggdTBkQosPJadtC2yzGaYT +BXG5hrHywRiEIFFsW6LqndQXF0T5yl+COkO/AQD/qDbIEYrTjq0Ii4g8eMYanZsw +/io90oefQijfyCrBbwf8DB2Cn0e8XI3VBRFonSc5/kMLK9NxV/W2VL/FqpmiU+h9 +dxo82Gj9/LS8FQ7eZueBhmxrPDQ4Le5jammAFi5d3kLxRLzeI91CCQQCI+rIXAx/ +hscjdEZ9SmC+bBJYuB2COgPW0B2FtrZJTqcI2OzPtIVBOgmQMOpBzol9HhYUQ8eZ +33xSuPHGP/tyHrFRnfXs2VUAI7K3R4Aybs+2rP1KOiwFkxeVPavsquB67kivv6vw +SE+X9O8l31h6nPdcp2rp6afqlZc+9xkjYNOPjvoCZBUzjZJmsPrGZgiObzdIvM0w +NJBPip6sGiFPqFE+ngT6mmDZhxNksrlcrGlPuWw1lwf8CfrQ9f/xUR2xDYaMvr1R +TC4vezQrJIiQC81dztfrWFL2jIkFkNLLNHLDPuTjq0nwOWH6/o6NA3Bonzf0VT46 +ZAyJb2bmw0UwopbYfpibHzWwRIQMagseBr7Yd9TzrM7CXm3JvT0NhztOtaXTWRla +nkm84yKLTj29s6yRI+dAIHbF8rNszcDUsB7GHZzuECJ4fotzcPk2wY8uAMvMrLbZ +zgTS+JIl8fqodPECfk8NdzaCVrhEfGJe9KgkC/ZrY6f3HndIfp+Qq+51hvi9rgqz +t3sHbq+U9oaq9C++GzRItMdV0NhgYdWeuIS9bRM1gLVvLmunD2t2eQd5zPAWweb+ +fP4HAwJ4N0sB4Ozuq/POxYHOfRbO7cjJhMcGLHjQ//4W2CJO/fqAJiC53KbZrZ4o +E4BHmL66IaMoamWEohjJ/mgY42PV564T5jH90lp8zt3kQUimtDhUZXN0IFRlc3Rv dmljaCA8R251UEdfZHNhX2VsZ2FtYWxfMjA0OF8yMDQ4QGV4YW1wbGUuY29tPoiK -BBMRCAAyAhsDAgsKBRUICQoCAhYCAh4BAheAFiEE0rkh36J3GxwYRfL7rZwFI+OS -eJ8FAlyH46gACgkQrZwFI+OSeJ+UkgD/XRHk87lTEAZc4bBhE0JpTQNwjPttsQqb -8/vWfcMo9gAA/jBhreR23DFNSUKssWpMfehrybb/Eeh9MTdjlxH/gx8TnQJrBFqb -/CsQCACVRtIa8bUCEDRjNDq1NDd8cFaGxcwm63tMyb/VvcwDpOEttvLtqWVefb9k -5tblykP2fRoXuDPlaVZND3nhwoxEQBk00Z5Uy4HcDnN0tncsD7W+us1xJHFzqeC9 -lkG+gZNjpWeniWaPFNdxZA1a0CW5FGkPxxfeRPZ+NtkneQ4D8/XwOOeGW3vUStAU -zqm+8ulQXvJm5CG//Ek5xXdJoXc/EGZV54lfM/867+FT3vX2wocY0MCrkJEHqQbh -i/xAbzSht0I/mwcinf8ERITFfehMyHKrJlJBZrpUZY/rIJqYx9tki8BUKbVUGuVV -Zij0MTWjMGj2C5BHm2Q6xCjmOskzAAMFCACObi4Qd2DU9XfN1ggp+12RCLM6TXBT -JPX3QOXzPICh1byBL9uz/fzBYibuDGINF95oPO4WWotKIrXwnV21yVm2jwFvRhGc -sdsPygkPeWI+d5dKjMnWyFeKVEQe2m5ah60392a6mfd5HJMNoYFEX1hs0FNPjBBn -32mkx8ApSL4JzH0gJFku6sJBu8rWfWBp8l6ejDA5/0xQpnoGYwKzNl7xpHaMGy79 -G2qhN19yeqkbNwACG+UF//Il56aMBwUZHHS0gPk5ygHNer0EikAoqLj7MhNrG3M9 -Neac/vaCikrHwqCiZo+ZEzNO1vgv6yGx0AIAOLOod7q3o0fk9+AsheJ9/gcDAs5U -QYBakUGB7gWWsInoS5D0/Sdc0rxiH+nZIy5ovDtSnP5U2A/gzBAmmO47T/G7Aiwn -7cJn1DDIXaxMkZzJG2OT7+On1jmtBywqhrXaEGqAlrYe2N8C68HO04h3BBgRCAAg -AhsMFiEE0rkh36J3GxwYRfL7rZwFI+OSeJ8FAlyH46gACgkQrZwFI+OSeJ8CQQD+ -J6JL0F+0o/tdqTgej2qqEzVlJBbGsstCL2UgyhyY9GsA+O5Mx9J7wassKXlDIJrp -Cm2wRCH2YTRPuCcptASW20Y= -=RMmf +BBMRCAAyFiEExYH2vmaZXwlAAx5mXkK7knjZZYgFAmFe77oCGwMCCwkFFQgJCgIC +FgICHgUCF4AACgkQXkK7knjZZYgCOQEA5Xs9pWlvMGt3bpb2BUJD29SlXHZEZd9P +gMvYp00o8QYA/i4zzXQlylJmxBUsl049u3grczsxMzFAMUjMpG3f3jflnQJrBGFe +77oQCACZMlRwMzn5ENx1RgbwhTjd5OgXwpw9qlHD2fLhPzLKvqJwhiKZ4NFA8Y0h +oBH5ExyQsTu3RiVzXChkJ6drBhycBgnmBUpIlUzqIvzmB1Xgl4OzKEvzopKIoYUt +rFeuBjtTWvD6U95P7jjJ1ebONFMym9D5sDaCNkOTHR+TYsEaqk3Aqa+SRByTsdtj +jp6u7Zrr2p8kHG/QE+uQijYdgX51HMGn7iCnqqeTPd1Wxq5Aex6h5HBxhDiGDPNB +WA0X710U1DcCL4bV7bS3pKl7rvj3VTLgAPVPyoxIw6HzfHgUKdXhA6zOtNVXaQUq +w5leuP0NkdBaI40GsG//OB9PPtQXAAMHB/9RPVTapSM6BoC54X4YmaUh9uVnCpvo +mBWIYK7H443l9Seos3WPPGLIAI4OZ2YyCn9S1oDeNCCp9ZmyOgtovL66gIyIUEnJ +FcfuoO4Lyuuiq2MjBaWh92u5Eu8jFsojSveXM9UKyz2dxJK2h1KgE+K00bKmXt2l +Yq893BjAdAylcoFOj8vr5y+9B0nj6XWVqxhWNaAOrE5/8yAUXkx80amkTymDhIVQ +urs+nCsZwxdPcW1KIj3rsm1RuDwCKI9t6hOmorb5r1/6NpaWasdRwUz7Y7vDtApT +oe8hMAQsTU102pZdvAj47VTaLqDfqyeg1MnAQ/b5XblctL70WGxLLYwx/gcDAggj +JHMvpE9X820u4iPfEN4e6vsu5VHcdGl98o6wbvYIMNCnCGydkLc45aC9Jr46FQKR +7ReJR7mMUm30I/1amGcYSjFTZ76a3HNx3dd59GEIGT0QTtOQRRTBsIh4BBgRCAAg +FiEExYH2vmaZXwlAAx5mXkK7knjZZYgFAmFe77oCGwwACgkQXkK7knjZZYh5+QD/ +R3a5LHF0d6uXPzAiqVhJttpJkbxl+SLqB+KHPZbc/58A/R9Cj150eSVMSjO2RI75 +Zj2jRtKWBB8x/2SXisZVTzJb +=W2Y0 -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,44 +1,44 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQOZBFqj8CkRCEDU9Q+bcdnGmp6Vv7gnM35+sx25nQ2xwpkFq9wb0PVeOPPMhRcr -P0fX5e52pzwAk4ZqGFqUbYupFzQdK//a1w59ZXt+QkkUsy9Jel8FEes7HY2FsbEc -cO9of4eZm3cG2ujuRfUDoY0l0sZkFqPU3fba4WM/jYZvyPLS40c8zv1TQQtp78Ex -sZ5i1G9TvCs/uKxQBfpF0EtZUblD712eRZdbLf8wI5XhC/zQqdfdY8QN17A7Y5gv -RSOeJoWfbd0VXU6rwAY1/I1Q+1K9j2bG/HYpnAlWjsYOS+Ql/0G2pjtlPK9PFRHP -aXJ0rIuQ9GCQoynDez02NTSv4NWHvR3EfQaQn1gYnVM/m4MBAKXj6H4rlGWYAYOl -8MefTQpdLOViE3zLbIIKpPkeBDKlCD0aUQB+C1yaNG6oCCQYIx+vvHPbD+VtPy43 -DZUM7j98Zm2OMZtCXxqFhFAdk+uDn2rv3VNBYAbYf5x+fFGGc61LTCwSLFnypGjD -XZae90muKiQTR+FAzObbIwIDz7zaMH4h3XeBeWuLmEUCrqwsFRsfRE4Fxi7Ur/Ox -wtUZp7fFmHQ0wPfOgvvYd8cNoazYGnL6p/9Vq6WXvPDwAPp7neIslcyJmOLoyKHF -/8+wVSPTk/Rbx3d7P9uMKExUo+lBT4ypb4cI7wGNRJvnh9Tc9J33SV4DHw9rlbcy -oGMfD1XpzvJx6p8Mc8ypxL9ikvKZmQnvm6HL0hCXl7XRl1Kjg5XFURzxP9YGXfEI -QNAWFOvVUBHVcaouDbdA+li3aH2U6wOd7feU7OCz1ndOk1u3kluOaLaIpsRf653/ -KiduMerbd+tvzmEufulToFVFuZnM83DUQpGLw2NRmG38fRJFHp6Wha6Pn/tzBGgu -qt7G9/vDibSxbnJ8x58QnKolFvqqp+VOZIDuhNBGVM7Qf4m8snx6yV0n323a0FhU -SBtkwwQb3MdwZtgbLcga/vFTafB2A3W3nqrGa/wcml9mqMkOnxh7vJU4MT7j4sdP -kmt26t3JrJhphW/Zn4G13cyfEg2xOfjCpikh0S31THRIS5ZStH5HYJ6/mfHe+aPs -fP9p8RNBSfBPO96OtVSQpAKChT8wUKA6Ov4HAwLsvl37uJhc+O9Tk7jpkrGkkivv -PBHoS4POxqxOZVFO2ryUEnMBa1UNjVlKIiXghVwsc6apaw9ydPvqT2I+17IhIJh1 -6oPvebCosQZO8cTBtDhUZXN0IFRlc3RvdmljaCA8R251UEdfZHNhX2VsZ2FtYWxf -MjExMl8yMTEyQGV4YW1wbGUuY29tPoiKBBMRCAAyAhsDAgsKBRUICQoCAhYCAh4B -AheAFiEECARoba+TiwMKqUnz8vxD7eJ3kPoFAlyH46kACgkQ8vxD7eJ3kPq9pgEA -lOee1/BtReSOX/0tukdnmLROc4kgut7P9cZz9H/jUs8A/13Z3TC69OIaQ+aG4MQk -9e+aoZXVEygfzyUz6d60X5nynQJ9BFqj8CkQCEDhQMWxSdnxHLjJj2AWut4nqWYv -9qKoqy0y/3q+nCsT54znCbdyeVJnChBjiOhWbm/g2DLIXT3I46wZj7EubIe/v6BE -yScMe/IYDgkXwd23nUM6tal/aMeNxC8IauDrd8dxD9pJF5zJyrBcVUeqJxtErs02 -wEZPcuhaUd36UPchiB4Yv85/UlJeyMWgRuC6VG13P9oKsm+KM6vOgqfcPxOMclIu -7E79MWQtVxW7TRTPQv4NO4lSiI2CqJM+c4+DAmmvmVhaGRiIimAqCkmBaP59Mgic -yldCBM6VVge09AwT66md+72jRvoyfgEFJzKIXrb7Y5DGv43wVZHUJRAdjM0pYiHc -JZb8BtMAAwUIQNbZahnxJ3FJ4nMfylxJ4In4GT+wzzbsObsgKTvYuwhmKXJZL+rG -+Wt2ymqJzFVpzhT84+ftBE2cL5ns6xEM+RbQ6swbHSLPWnPMe/2mMt+2OWPBf/Y8 -MN6ZRFhFR+7IbK/FrEIcz3HgxvtTeFuMv4efJQEi+cjfYiI0YRiF9GbUWRbQgdqZ -+K/BkpZIe/KjUX5eRNOYcuTWIouKRGPNO2LKPQ6diDA730/bAS/JgRetBWosjglm -+zkCJQjguC/sl/lmsI1tFaoLB3cS5RbbCqxD36UhDWRzX0LVec6kKNZM36bfZXzG -WyLmJUAj4FkzMtbiiajckcYpAYpQlyRmt+QymrtioWYlV/4HAwLX1uXw52T/hu8M -XbVt5wE+xAtpJvNksX31L8W26Cs/gWQpz6bylmKUvFGMQc9rrrdmZOPtzWj+0wL2 -NxU2Y+BvjKUFhL2RjlqBYXZ7PTbL4hvmuNMtjY3QLR6ym4h4BBgRCAAgAhsMFiEE -CARoba+TiwMKqUnz8vxD7eJ3kPoFAlyH46kACgkQ8vxD7eJ3kPoIdAD/R6FSxoF3 -0kQavzuls8KlrQPetWnu0/ppsg4nKWvcD3wA/1GhALmsLJwRslzUnR6S8CtsO2tS -WFiUirf7sxDMvvBt -=B/zq +lQOZBGFe77wRCED37yrq34wn+F1PZoMdYUEG7VjCMSNemATWbEBq0KmoQPpW15Uw +tpmwYRK9S9fPhS+A1Sonmq9rMHjVkagtzqyalWDQzlVAXY2+KxURMPC9HM9m6pxD +1buJtkNSMIkt1DisNKJ1Tdzi8lH0JW34LRut9PC12EB/pc0YhCKFqX25YVKD1zJa +wuDJIuhVOHscYdh+ZZo3+iJO4+EhY+IlvmzJEArDVUd1yz3UaTb3lu2/00PQN/jQ +WLNEY3gFjALtxhMYEXMrP06fmYISmhOFvucASImwrt/AkH49J/MVD7sGSLxI4FRE +vjItjZzCvDGacjMhpZH+mMKTUBER0WibdbwEQwz/rh7RPfcBAO6YSMpkjQLk9/yE +rspcEFGnDTjUFnkyDeLA2LLw7uaNCD4h4nTKz4/adpVrWA68Ao5VX1PDmudzlo8d +8gsl1xZTBcUoY73SZNZ2muPAIvQicjocoSacxJIr53AA4Y2iR64S3Qza4LwWPGpy +PPU2mq7mRvJtjPj85YpOQjBxE/4p10EojF+s8SiSbvJ1r8W/7vUoxvxt0aNXb42/ +5D/USn+JHw825s876e857+VBFuWw699+iGMJjSc6xVKVu2EhTOe/fFDYuyfBXGDo +L8Kk5U/o/kLET/qcPQHX1FZllSEDhTnxdI7g4Yhc5lrsW3JW4ClVxdRQU0wDnBWR +qGw/zo2XiXGCjopj1vusvUgiOl9fQGFuKnn5YPmbCHuYUr2PE4FLd0o5Z2F7OD0I +P0ikdSBbXHhjrHcv6F0qfsQf89uxQz1sZxqCiW9XWVDOisJ6QL6mG9YpqprwdQRo +EuzQnkeNvUpW3q6WCpFJ02Z11RAvsH0hXcZqLOCRsOaCI/8cQizxDjxWQJBicGz5 +PnrxctoRcesUqT3pTwR/LNPG4hybXYV/PER5I5kak5VABTtSfe7aprwpwuVQtYTk +PeIDvozRbQvnNDvZTI9WUvksVw1k9SLnRYxEFtJVpLr14nBq7m21fAURCQJVO4aS +jri4l5IPudvOpomehmpdzkGhMKqrM4RmiQV+zdg30xKtqWBABUClDtO9K3g7kn5/ +UsJEBaeE/LuD7Ccy0N2pQqTNCWs5YpqhQv4HAwLILXCiMtOTH/PiGbajK/u3j9aC +9ms0UxQgHabQVr62/82OqG+P1+y8fKQ5N1UTP7gj9CMjZvWOC2XWF2r5o49YPh4T +8jrGem29EF0G1UA0tDhUZXN0IFRlc3RvdmljaCA8R251UEdfZHNhX2VsZ2FtYWxf +MjExMl8yMTEyQGV4YW1wbGUuY29tPoiKBBMRCAAyFiEEqpDB1QKTxxbRFyNG0Ikn +OFcmfRoFAmFe77wCGwMCCwkFFQgJCgICFgICHgUCF4AACgkQ0IknOFcmfRoStQEA +10om0E8M2s4/SbO74s4KGTZ7kKbNH5HRyLXDD+SYtrUBAK16METgvKrP5Sva4/fJ +174GurIrsEYY7RHiaM+hBXexnQJ9BGFe77wQCECRpuV460pIsG9kDm6APOCZZhJN +in9H3OudcxMRIJBdnphzVcYQ315o7x6tp1v1w/9b8L5q+NhGdSfAHOv34poOZPeU +3ZrLu7fTdDUyB1a2O5K5xrvE6E7HdkS91t2rm41wyeC8jXcaXwfatdtSZ+ID3Ehi +0Vz/gwsau7kifkXWHGwgtYDqI1qDq3/rwNEF19fyHNCaiJlc+t9+IldxaU7oBAMp +1wwxBdqi39ux+H5nZZo2J2gtYXV7bdyKGRC3RteDlrqDFEZkNQYkNtKfw+ab7GD6 +m/FvvZpjT2YYa3WmRvVgyiNLu1+zhNxbmVLbIUf60kLSiZYjB5OH57WmwN0NB7wj +UMmx8tcABREIP0plXl+piBC5FmKIJDb9Ha1h0YMyMKkURAfn6cqzcRlvQCfXEZHg +jAY3YG+h7kY5xjj9gHlUK3FOynV+GsUVF/dWIk/CO9YEHSj0X2z9Vsr8+4csqXIF +IBwrUEZFY1MrCkY7prxrp+JGfbBOUIvRjs/JF6n2NfzSSSU/niR80/jjVUKH2FUO +BP5a5KSOWD1Yc9JHWpNht0z3Pm9e3hmxtWH17HjJZV1+1pSQPiq4RjKRSltpB50J +GGJMeN6uOzJQHIQH+64awCoYNTUdeBdIv5zFgdlpSV8LADYWbh9hpFfN2BnYtkfN +9RTXoJBiRZGkwVEIo6HIE9A5vXfR+8dsLCBPlDaEGZFxaP4HAwJETL/WgJy3fvOX +nKaqe6ny1s/wPF9cUdf+TU6/XGa4Mb5tXu1Ab+2/jNlJV/JzoMREbj5ifzUqqsng +jgRBR2dLGwoenR0suLoJvCZDVpyZ1t2ZUDPVe6cFrLFex4h4BBgRCAAgFiEEqpDB +1QKTxxbRFyNG0IknOFcmfRoFAmFe77wCGwwACgkQ0IknOFcmfRoHrgD/eeFhKw2M +ZKz9XC4npbtCPumP5+z1fJtXIP9PGfB0AcMA+wWUBKt8vm2s9J4TEdFC+ipPdehk +Tgi2eoTVV8l2CGmV +=8SKT -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,56 +1,56 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQUBBFqj5cYRDAC5bvnU69dUx3eCMcI61zLEqlMUxDv7GZG8FHnZEgF4nVfJQxLw -6nEyWrC6vG0QLwPci+92kSpec+Ni9rnf7BqpfLpNBxfYGbHoWqa0xUksViWaQX02 -4MJuW0fsnLLbqF1BPYrVyOPJHERSa341iLyJIAZJs9rMEZtzRiwuDIA1pwaBANEE -sohd/xYJ3XD964NXqNYoQnwmOC+16Tucbzm1Hla4i+V1Rt7t6kitxowSxTYvkklp -fiRpUa0Zfi9KPyEirsCrPZD8ySojRIGmofty/3G/3AP/zsuJfN3w66kTQTu1Qj2B -0HO8YPnOp+yWCyTmk6ZBEhVpocO0ERu6BtoTs2kh/qOa1ZYqS/GUzDArxmMcL65K -+o74nHX+m63qo5OVQByoP7ioqao4lq2/iIJInEXnCTfQ9VUEG2WRlpAD4YpXFHDn -ELQKGS1O0vjsSBMTJ46L6w+6prBG3rYiWtWu1JnlEEw2c6DTaMNC+nspgul+ixwU -aXK19yvzOqkeq28BAJ51B4BkUOaazmR4S/i264T4U/pixNHCo+dO7Xnc70y3C/sG -+mD1/r5h51D6QA5xus9XysbCnbYu4R77W4pHuYsUnzLaTAcO3KFpROJoOYkeHz// -Yw3024h6/C1oifWLZkGXx0CpSpe7G2qXJgmDtA/9xSq7jWTN7zlA+/K5xozYXwCx -HmuvovHba8MOc1IDHOgMnzoRjJ4v3pfnGeoACVxkqOQoke7EE7AZqr/gcagDSWRN -bOaw61FYB7turjlKeK/SUkB7e94I7PwzXCBWs+zrglTCOcr6+2LO0nbV+k/L+ICu -MR5pCzUaNZaJnxgpO3SPTH0RlfO4+Mj2O5bD9PJncmjoCJlJofY2ajZpNp7ULD6a -Kuyb91Qs/VQN4u9AcfSTTicyn3DixPm2uM0dkQRAUMLYSDVUD6ttvkEwvHfMe86V -2hb0l/3nOmP8BijJkFv+fm4jy4Nw2E0ZFGVTAZJyf41E8i1Su4ONkVHbjkISzZXF -eKTotaVJzzqZQcgCeTXyLDvzCog5V9FopqqWQ3TmCijY9JQkum5/6+BNZYxCZIEL -/0aZjo+IqwvgK1gyNZXMFXnc+IVXDM8llbevWU8nwKroKUUnKlW6AFRJxdGZL6oL -dDGMNcSt2mc6tMgCn+KNX5zWNQ1H5xVjlQFy4mfV7yZMy4uJv5vMM2gjZ1K66ayF -FfyykJ7ZoYU2XC/OPFlXXLim5a1So+4LzluguYHvfKE0qfLB7yg2IEdi5PykpWg7 -3dMwv/2FDF7OzCwebGrN6PHzNxo9U/3ptfEQWGKTNtomTfnPw766TdITiJBppGrb -yqVJDzJMDXCQYwRBBEUnil0M8uuBLAjMPMMQ+JhTWm2fIJ+UlvkHgWTCk7jDjjdq -rP7KfOS9g2+y4pbihn59qGGyukT7B0dgU4ZPyC6rCjli9tFU7qlLQPGGbWqT8Lf+ -VmTHzPzdyqT0zuQqXS/yFiEvUW8sVeh5Ivywqa4IQ6VOCU5j3UAdiOt6NKIX0rlZ -ysrwk0jA0i0hGBf7naHjLswv9R16N3PI9i3+btgMSAchNanUAC/B70ao89ymuT12 -BP4HAwKQV1/DkpI7wPAme4SyPXHq9uT1lEj4IRRkIizD6E7SloC82qItmEK8Phmw -Q+mPVyhns0lMWh6GVazDGY3/K6kO+3xPSU10g46SQncCMoe7tDhUZXN0IFRlc3Rv +lQUBBGFe778RDAC0XaOHyZeis1AP6aOaoMiilica7bY7ap+oHbp4j0Q7OFQxN8wH +Iuu8eqeBUPX1Zv/sBxZkXcN2mJU5sPw/UHg3+jB+M60R8ijYfcp4rDVsi1qGMyXO +Ev9fVAXGxxCxMwXZh0c8b+RDYeMJskgAhpCU1lbeDnOeJDCd7ERIhbTssAtJ5DDN +MtEOk6zO+ncWMlrWs9h0raeOKAx7aXVPbLNqWzs3AE+krHr3VKr6VAr42kUvqYta +GWdx8saySvNq3EDTGxtZXrpNEQMwQhjJXTshXaQXAssq1rJco3xl6onaXSLE0Egd +Wz15VB1CFcyDFu86DNlNbDLs/R/zW7kHMfhqtaRUx/tsCq5RjxFgPExAsx2RhML7 +wwR0TDu8ed2j9c6ZmytAoxvz6ntmRVYCA4etFRv6vx0ih3EufuM604hqzc/HCBAH +vzFHvmhmzXB82C7szWtJ4mHToznDWbTArPMnZ637jOEP7VDogqQC6Gx4lawW5HAM +Kk9tPm50A+Cxx2sBALs4T5J1KZwqidKUrKcbe19bODPDdTpvUp6TYCaYKvTfC/sH +owju/tCBWUW6qKRLKsGNiYL+OzL67I0c1W9gDXslPfwoclJaK0EZ0eNohlELodQz +PTyxrSnuR/TpFZKuVw6erWX56UkO33rMi9IXNOjUfQMedy9/EUmNsFmLj47WJzzF +8N8v7RrKy1NHKRN75LKImj+aJl2gc3UwExoIyiV7gX98ShEUw4nTr4HXzJDmnRaU ++ijwKxlBDPs59yV9BFo+419SisvLFTu3ObE7m3R77uB5qSdhs7WOGflQvTBlltWt +Rx6uiEiGYE4oCcPnu3oN2gK6bIrt2f7cwRWc42IRfhcnoEipKQY7x9avBlVjtnxk +eRISr8RaxboLDGQFSlyFneFdMbkEPLFGuUQt5NUF0sZ4BNPKvmo7WDayVwyY5Xm/ +wu6fbjUKWfZ6ZePWKB4C8YSFMX6YW3/SjIlAlG/oMLi6XmMehOd4DsbJh5r2j1lV +ov2HfDvRs+dHzAKERNtxLehB1M2YXwI+yXUdxYAtrOO63vAp4vxVKk8cqWafN7sL +/iUeFnCctrSx6NY9RL0E2ZS6vX3LU1X8dcrRfI8qx2wiIZBX4DZzwitImNv0+Vx2 +ZI/8yyyIB+LBIpgGF9DtADXXzlkru0Ex1UHB56+ioFTGJyS7EQTduV7p/CAPDC7l +/OfALHgFq9Y12FY22HrVXiXkJqF9Uu1KM7N1nd7kKAMZsHi+z4BiOWYgqvTROzCU +TNJCsXHTf196Q+DJaQKLa/tHXdhG3UWerO68yYpznObw6e3bFzt88QIvBubFcWRK +s0v6BsyqfHUY+WzyqK8cwKEflE9/Kh5diQjIq87yRBOUwtkEKYXFUSt8FZxAQWJ5 +VlbnjFuJHwvWsnleTQzUTMIFkBD8QSDWwi8iUof+rgxtnOsP4+SnQA6pTiEfgX3O +6VGkxqwsZY/DCKoCO9pW+JdDK4/BGMcI4pwQAx+BgFe63kfmnLzLYmaRzGhkRt+1 +ZhHqmld4ZsMu9wZPQZGmQR1g0vUaci+ats/Rlvna73Z9AzPXwlEpBRagmHeWwimE +mv4HAwIZ4Lcs0IczrfNPAgX/XBUrXaPV+b0D8LPdeP7Pe6YLQUE1Jhf1vBsUF+kn +9QlocqSXMtEOnp9F79pscAO+9W7MLEpqrsEHYajEynPjHaI4tDhUZXN0IFRlc3Rv dmljaCA8R251UEdfZHNhX2VsZ2FtYWxfMzA3Ml8zMDcyQGV4YW1wbGUuY29tPoiK -BBMRCAAyAhsDAgsKBRUICQoCAhYCAh4BAheAFiEEYPCkRtXhKmYYvezdEinuUb4Z -ouUFAlyH46oACgkQEinuUb4ZouXzQQD/XAf0pvgUAKqPVxx85kIE+crzcv/X2HgC -52czZUIICFQA/RvdVqOZDqfCennbUiYqOKyzJfsU+8/uLISJNIMNvc0AnQNzBFqj -5cYQDADbMPGkq7nK+OZ+H2qNC3nF95qf+y0viA4U02TE/SCMn7dVxeKZxs3EnnKK -0xqIVAoCYvIv5tLHlm4Psg+NWutctaSmoF7eNbx0IJL5c7WpQH2TpoWKQA3Fyi0o -Qy1/OK2V5Ij+AKzr51uxcdvR1NecLjFUDURsvtJ86XCuYhY54rl1wjIA+wpumIp9 -N5+/qyn+mxBe3/C9Mj+cIpQYtBLVFIBTV7c23NBCGQ0Gw0xr53ontEX8U4Tqg0M3 -F2V4/eYFOLqZC5RsXkA9vLzzZMMFr9AaD4gYibTIn8O3GmFsa4PwB++HiMx+D/42 -e56vbc2nd8ccJgtEWvtD1KlOouKpnC6YN97200ePf7Ccl57qN3wnEO+2Lxhx3rIH -1GwQiDGKcKFFZG2FRaHIXPlDYFanTENF9s8nYrbI1IUyTOG0Auu+Ki7TcIIYz3TH -NXV+y4/yeD9eHQf5WvuKccUUhMTxxzPRKXr2xQjgGtAy96voxS04hynQv0IGedjh -4ZSP3D8AAwUL/0kXnYRZ9zx3SNptw04gqClOf0dsqxmlhXqibsxrANSfA1feuN2E -UnZulpUjGf8K9u4YZChtEJrGJvefQnZC1hYTeMFxKqZiHU3LO2ngCSqHt22FTkE6 -vpVmE+3eG/xgeWOlG+MSfkQZtQBG6DuNZW2rAhoFxw9/RM/Gbso9ntNPp/UBfjeA -5/ZWWFmg2dTfvr92wV6vV9n/xPjBkyTT7jr0zK9NE12s6DpbBbUlNRdc7ihSHHjE -2HKI9pRwhEoRxmH3n6tawF64F4rNZtHDKKKzq9DVDGXgSD/fWLLw75yoT4K0vYog -24MTuvV8ka0ey9AFUnPTihXtlNZE8qblo56E+FFbhv4hz/vV2K1+ABJUe4blyA26 -llkpbKittOlz1qc1EMHrMUMlTyvN0AkkVgIyl3tVXEn4RO51os+2XxhB6IN9P24h -1wMBNWxyQLgbli4ZCZFtyXVDD3wgeXqfupg84pau+IaVYQDfE6jeBzq1Ha91hnI0 -pLEeIRv8RoLekP4HAwK1hEZDS+W4KvAy+nTUEk2/oteR4oNgvDPQoMKKO7EV3uU6 -42Q8GTcqPZNfMicT14+jgPWzoeqOiG/UNgsbX59e6mbKlK7+0EcyvWs62pcQDfDG -74jIkOY5ycQbGlKuEgsxYoh4BBgRCAAgAhsMFiEEYPCkRtXhKmYYvezdEinuUb4Z -ouUFAlyH46sACgkQEinuUb4ZouWWZgD8ChBEjfiR39zWq8r4nDjhOXKDyeAJLCrN -Q+epm0vGneUA/3mQVBkR2lIoHnGEpi7oNCVpZ1Qh07xkWov8ahXpe0nU -=O/7d +BBMRCAAyFiEERvFYQnywK4J/bhDVLx5jM6AoTOIFAmFe778CGwMCCwkFFQgJCgIC +FgICHgUCF4AACgkQLx5jM6AoTOKB4gEArhdCDlHenh668xWezzTpiIBBayUwpYqk +u0eA2SxNDtIA/16oRrF/yNG3SBQik5hK+5x1qnz74Tjy4HKyoQZG+kf4nQNzBGFe +778QDACgUwrNn0SlyBstTzLXNEfw/7EcStgn0/CJR3cZ0lGzBiTurh5R6ZnqOMLQ +aa3KaBg9Q3Z1wOe6MMrp7+ZvvY4iGvl1AKg1W8g2X/qdGNtryDLKKuxWoKWa4MHr ++JGjBzNvUIRXdLIMVxm5iwO1uSrlsGPPqY64Uz8tlCAXA2Eck75MvOOMRBEG+XRL +L8XYb0RQFNeaIWe5HScpbBwOOvX/2fECtyuEzYTxoE8IXE8sXUAvzEfd8BK+hhlE +aEyyMqfdHr8/H0Rz3bHUFJwLVySU6/bVhFR7SM8Ed+/SKfR34HAphnXJgplrn1Mn +zzYVLvrORK/pFmy2++rt3mYMxyjem4oLG1zK1eq4kl74Ugl3Qn0Np7QN1H4C1vyN +sms13CW8tSxMHhbYzURCPpHHv7ewBrtPnOztFj2c4FP8nYUabkTQGn1JrIoxv8xn +g1uVwT2t4CHeni3W58jnW/lqFJlE1ehlnNHIdiEf1Z9V+6lBl02BLhlEM8wxp/nR +g+aDYtsAAwYL/3RqobEgdkr5xctnI5VLXYisvAzd71CgwcK15vqCNxu2bHW/sH/c +jNPS2Xm6uW3WDwVx2WG0ikWsXsy/uIu0hxiABdWQYZbFuQ2fv4mjbIyrSrsDsRgV +CPaBXY+6ghioUA/LlMcZThB4iqDEYeYRuPUVLa57QssVVh+/7ejjCZQqsys5IO4d +RcTm2ci5/nXtle+SZvKRYVUVzL93PUSsrr5A21SsfMKfxn0H2zu2YID4HZnDz2Dr +1cHgpLPiEPwNq7KKfk9KJmuphOaRN4DYapP+IICP6BnCJ9uoNwmfXrvIWAAP6HE1 +SWVWQGwNZZaIlay/HEyIlLJnh+Sy9pYmxnWMHiYXFnfWgnlRplP+YotZa1jRpFXF +UwNialqLCGXphybnvCSJwVHV/VAM9uWolcEMWkNwzafU1AViGdsL0MLWXBlY9+Md +sjmX+yzFDnQ5KwjvUYzdjHs+ipzbhCyhDccvBML9TleIiG9ygi6nWQnXeEhIL3E5 +RYk87L0R/Ssbz/4HAwJzHZmpKLqdw/OynF6WBvtolrY3E0Zro+PoSNWirz41wIaE +f1BqQ4EAFfT1RNi8UCyc0fQeVDGjBs65IvnPmMEf//TzKIIEwkq+yMBR1b3ANEBJ +Ld3yt+0+7bfmLh3V1csovIh4BBgRCAAgFiEERvFYQnywK4J/bhDVLx5jM6AoTOIF +AmFe778CGwwACgkQLx5jM6AoTOJc6AEAufM1yD5RPXZjHvrLOp7EVTsLtDt3mGAf +ewPCBDYXFO8BAI6PzkrSaz4+CGVA9I/OJ+xC+IoZhO0+cYy7SRaSkHjY +=tIv0 -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,35 +1,35 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQIGBFqb+ekBBADOGgzyMuWu1xIkoN2G9pHoSSKKLQd3c/VEbkLhfzTVenPJIv4G -7FGUlYHv0xf/XBJ9NpthAI0Q2XVdCKGIc4yXZkx1blR8dIeZC9JvYfax2ZFxuH44 -NNAcxhIsBnC0udCKttKWYypAW/+/DMuAW+BUD6NNlnomKxi0TpkFnprJpwARAQAB -/gcDAnALqz8h/OKv7x1Z2vjZ6MoA51xCqT7eMoO/qZTAVV3Slqh5SVz9tBfolPpR -9k9GBvCymsGLOtZkBxJYkEg9+mts9F97d9aqjw8eU4/Mur1egIbGoloc2NRz9pb9 -RGF74PmII7YBDFX7r211UBOR1RMOJpkjQc7OUoyTtDE1Cra2+lGm6IyW3fq946oF -bSWwkz+vuASGrOyd6vNwrv72kvIWQQ40rD8f3yhC5c6yA+11ki4NnfrRWw9jEYio -ILbPCdVF5XElhSBNn+d/NmtF+GwP79t4YdXyzK6F9ZbdqPbI0FsnB/ZU45AwUGlx -d0oUiYyOvcQBNJjdoTzu+8llqRsi0vmYfSM2WIxABjjgaa9H17WpNuSFWMDB0i/P -P442lyZDbzT3RrtPiPG162n4bIx7e0F1THfkgb7AplO4rVOl0sITDs16N97Geofg -LDF4jPZt0C/KEODH7g+1BKI7ptC4afRaH0EfEoSgPC9OIlOFCc4PKTu0MFRlc3Qg +lQIGBGFe76wBBAC0aa6zzk9gtRgzdKbC7R+NFDj6xsFSnikdlyX7YSGDAa2rzAhw +/2E7Q1/MwPAQOELjj5++Bv+vGe7o0wkB7jCP5k+TIB4H8sJACNLr38Dg6u2ZhXrH +4la6JXkGzrsAK3EFiHpCI6JN+8naNFS9D7HPegGvb8n9z8hQfifrMimrNwARAQAB +/gcDAh1PRRk0jgqP8/5trSvENrcpFe8e3dLd5Tr0lkZeTfOHNSox+WoJAWFtpWwa +QII9XcjnpHhI5RaEjlmk5XbqHzBFEkJ6CziwciygbRa+oBsPcCEWU5p+JEQ6PQB/ +NZ42zGRL4ysqm/pbXLev+QAzRQVv7PANnn1XbpNWZPwQ4VsIAkXTZeUC3JS+bB27 +OsbmigjgvEzZCSkCsXpdtCKB0jEyEfdTnFYFEzXKJ7NQvNYAKRu/Z2rUuY5ARSck +kIDLALulohNBYV3URRjAhMOJddQhokWeHpctNgr/UW7+jImEySg1tuCm3LzRwq8J +Ou1CIT9Keu2Q4+a2CwunAgqNIAISYRrbMZDqVfORUk5HaR/wjnZfq2h9Xt9eky9d +logY4rPy1ap2HcgL1RlHm9HaDxoWMmPZ1geQHnwrn/lYxe2Ch0AKAHFQSjqXDcXK +CSAUQudE/I6p0SmcvjfUCTskUUFR0Rt20IGCBQS3Vn8T8bIXaxIrKBu0MFRlc3Qg VGVzdG92aWNoIDxHbnVQR19yc2FfMTAyNF8xMDI0QGV4YW1wbGUuY29tPojIBBMB -CAAyAhsjAgsKBRUICQoCAhYCAh4BAheAFiEEOZn6SwnfUvYtWVjnVz6ZQdsOKmAF -AlyH46wACgkQVz6ZQdsOKmAqUAQArjTUYh4mGR54GdjYRgpTV0kqoTzxONqBJN6v -7XNS3CHM1Z/vlEBFE9y4ZOipyq5D+wIpg0AQspLzrJS52arpoMOmCjuPAkXa/gEB -X1LAgONVCbYGu7Qbs1zrjcc9eRDskuB6757jgQtzrPqk0QCW87V/Gd/D6BVPFFel -m00wnxSdAgYEWpv56QEEAM9iYvnBsNUVuJ/+NPQCsIsqcRpvbVDPNZzyW017Mj08 -Tj/FOFXbsguxnjxVOKOzjRbbFqLteuAWeObXcmh7yDNrsnxR32mEloRIc3XQrs2G -AWdqO76vhVsxF+bTqNtmV1lDDPSsiWenKkypZK+9tEYW4/3uCAYYUlzB3FTUBujF -ABEBAAH+BwMC7YSgKXIheDjvTzQGkOcVRh6jV0gw4hZ7hPomrxuXeqDjrWT6BUXJ -z9xBIVJNTuSr/GZdit1cGjNgXebvPmKwTIxJ9J/rPaiBdcn8tRusII9JroMJzClq -WDZ1TUFtlqb0vYKHtRN5HOk/qy47Jr5dAsEJBGo7etkwslfR4gxtyXkGPy81kZN5 -1gcZfy0K1Ki5jzXT8ty+xzVWZeoyPfI76yeAdJsNOSD4b6cYjp8LuIdJphrDEHCE -fq6rWcOvcxE7FoNNpPouu2F6tWj41dF/Ix7IRX5lL6Pu+Lu0CjK93IRYw38NsgCB -Mgv5eEmFWUwXB76FZhcw1yQaPCAPOTA2A1hpG9QqCcGCC9Fd6ZE8oTvx8RQSyTde -vCOnoEQcZkSnb79VBV33vWoHd72aVNV/GILOto4qigkrNZJBsSB8Bvt09aayo6Hx -mDA6Yn17Moq5idl+UbVtk3NRZOlBhtmiyc6UXiTAxXzZ1YvlMSxcdixN8cipWoi2 -BBgBCAAgAhsMFiEEOZn6SwnfUvYtWVjnVz6ZQdsOKmAFAlyH46wACgkQVz6ZQdsO -KmACgQQAxr8zxjqsioAV14W+z9IZHG0id1EujMe0k385oCZhUx8y/wG3m2txWP3f -a5ZUuQUK+BbY+iLRefPesqT4LxM79QKKvipRf4urCP657MWzyRT/KvuXkBHJ9yro -/+Mo5pi+GZFf/6zIMe6Pvm9Cj2+TT7arwWq7eHdR4XDbMQ6Nxzs= -=eGZt +CAAyFiEE0VnY/u6vZBMLzgGE858hnbvuXHAFAmFe76wCGyMCCwkFFQgJCgICFgIC +HgUCF4AACgkQ858hnbvuXHB6sQQAsTF4IBe3ITTFX42RUsKsQZUj6lRZvexBj7q0 +/XqZNLcDpg5PI/9TMSxKb++fMyhMlT5/LZCN3VoMSD9JGKG9RHDta1v1RX++WV5q +e8l4mAEr2av/yoTk58Zp09yDnK5p2yQcYQTAdl6thaRW6QxDH2chCuh6+ZV55AeF +55anb22dAgYEYV7vrAEEAOi6+f4Tjjoujjyq+qD/7//P7Ykh0lCfjcUEdKcroPdj +8G89hcrVg9N4/5S8ywFTwP4ha8796PerP4vPQI3gJ5ZnHR54bfPPG8sdwJgffYoS +QDp0gHwrkYe7mTF+kMemFhteMAI4Wq8dGZ9X8vpSTvppkd5anMokDGMV/06fV9e1 +ABEBAAH+BwMCftwA6BU2/WLz6sLZXwxGLyN70GG9Bj8J/JqFZE1m4ALX0jhfWqns +oF7LREKxgOnSpyXlkcUMgKKLdTLfIKGg0WCnOMOhJuEyPnltl4TjxvPw1i/1+ZXF +D+UWOidJ1E/lP40l4ED7AFq7yIHs3gosz0B/dBYq542rpFsR0Pv2fpyaYsTHurlw +jZJrO6VlFszde3+wHVTplkQOeyMUVeJWxJX6KEGP2dBvqMw0WdlPaVO6det992Pl +VYfjpia6Ti4IY41EkTQaKSKfVQkplwG8aBorzpkOSbC11hoLnwYS2dPEsMRq5QXq +FtYQ5P/sI9Jmsr6/XxvAUcEgF6vVEGjhR7Yp/HN5umu61jB/8JQyWN/OP4YAdM2C +OdBZp1epaqPTH26uJrz6QfC6uDZjwwJVRTUtyXLYQI/63Bx9A2DAlxw2fPiBAq8e +gw9dpzWX2c6oNXH1DjiPnnPhw7TDizGfm6lLnDLLXM5wkN53Pgd1qtlWjp4nsYi2 +BBgBCAAgFiEE0VnY/u6vZBMLzgGE858hnbvuXHAFAmFe76wCGwwACgkQ858hnbvu +XHAdUgP+K3sBWOZLQFyDJj+on7M+l85XQ+mMOvXa7oSRmRUy5baBF2cbAbYfAULE +qkogTcpChgYz7XMRaX8/ajsIe0tp0HFvm+hoV6cSyOgTVGOib8xaZ5YcMn6w1xOU +XLMwL2UhsGzkrwwimSX9jojvJZ1vejdkvZHFJlZi8vyekyxS1NM= +=2vB7 -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,59 +1,59 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQPGBFqb+fMBCAC4f4O40tNUCRc9XAQfGzdrT+T3cgD3a0nF4ISyn36tSBB1uOXG -Pu0RXdtpp8EY9EyRLNYF0XC4jBERF7Mtn1nLPanrwe9SNA3wiJUEnqhvV4CaEKMS -tTSidlpknD8sGz4toZgHjGubc2lR/bdNdl2Me6ZLWLAoRTiSumWuaL00T41Vxlew -PKKPheK0lfTPykoagRp0j52/QdEK5PG+HjltRfRSj00jLWTcjasahlAKw/6kpudG -rKSjfQjWGV5sEOMRoiJONva0uV4ML/cpBnnVyz40Ph5U7ZfLneQRXqTHTbke61Hf -epWJUuyF32a+u/UWv5EQZMQmVqDvaK0qGyNFABEBAAH+BwMCMuwSXwY59s7v7zVS -d+m3Or+1LvWUzyDygi5bU6UWykwk5oWhuwUOSEOqRemvSKubaVFVrXS+8sR/+NqQ -4llfVpvXJV/dJV3LcAlJHvfxk/jm8zB2D7Y9uMERdWwCgmWpBE6uxzkMG84uGYLV -X+D9h472G8VtKfjzYd8P3oVXkjHQ8fmdGCN2l6RkKVKwG4UABQ4f19zaxbCMdfE7 -9YJnBh1m8VXKNXONTz1KD6RDVtOqN+UkG4HJBaCHZCK9HL8PJIay4EvC0Q0fEAw9 -NWphZHxQCryCUa02/6gzvoko9+pxUXgsoeazZcjwtOtIIeXKJ4DUMUxP2G8fUIVM -qcu7P0yeaPeU5zzVEGRSrmwYJGLEZRDzKfPeDAXLqgqGRAA7ogdtcPVpsLfGPzN5 -Cp+pj7qL5SzAwfOfiy8QVjYxFmLW1LlytR0UHnquMMkSKL1yqqLMVKVS79bPTznK -i3YJ//riP08iOAVH4T8q+e7BmPvHhAh5O1PqNOFfcTwdjV6rBLQVJqT+1FzpK2eo -bv2ry7dowaCOXY9tfRv4W30oYrKRpHUfGLsoGjcGHDEDzGc3SBq+H2CAn8mhyZ42 -6igHe9X0bwhzjQtINLLn6gY73cNAYNl6lLJKcJ8oLEFVAc2W3/KYmrKyO+09UJ2B -uPyC3Kd6pvqzwRhVkbfneMkeexHCYvk45IfACL9C5x8kVC26wfJXRcFNvEPI299r -OTJd8Gpf6dPrg3wP9zPxzCOnCK2VwjBzNnVJjtbmhjwJCy5t8VvWoaDMMuVLS/UG -8WxX62CKbD/ZEl8k2QW54SdJkeeYA0pU5u5rw3prunUv6ZCI2GvJvNDSnWP/yY+r -IAxksnQSUCEv/dJQcesuib03373uTJNbSaB2Zlj7b+JM3z8umUP77aHTGQNDaZvP -Px74k7ih/mGotDBUZXN0IFRlc3RvdmljaCA8R251UEdfcnNhXzIwNDhfMjA0OEBl -eGFtcGxlLmNvbT6JAUgEEwEIADICGyMCCwoFFQgJCgICFgICHgECF4AWIQS9VTWx -yWvwkUma41z0RRleMOxdSQUCXIfjrQAKCRD0RRleMOxdSZ8rCACkhxpX/LeZi9QP -lNpxzZAIzIYu6M+QKF4Ju1lbRGyzfoC2LwEKHApP5roPJUPPNfQqJzuewOPZQ+PV -yxlvQ9NqOgZkdKotEHAkhMPs+j0SL3ymvX/gZzX6dKHqVP+al0MY/sNIB8S/dLDI -zGxJa6fRHQ+4F89IMnCwppCDYPzLIdP5frtu562pnSA0kKqlJyzxAmNEYX+YFBoy -rhDG3+kOyze2+OtTzXhTaZ4e/tCJ1eCIC51HgzkJWFfy4eqS8gSw/PZB47Ne+iNL -L+i/X7NwSxVTd6A0lxp7GLdCS1R2Wz5TM/uvQdcQ4ZlqkY5RC3L4tz8E71Uohh0k -trNEa/YGnQPGBFqb+fMBCAC2Tsx2cKXiM041H0YMCmrnB0iaURfcMTJ13EJnLfAp -WgaHT/8HsmliEXaMw41qz2OoepCf9480+UTR95sty6z21/MlFt6B5aqH/InsCToG -Y/bTnr/J4Xoa5UuwJFEMxDVBSt2E6LVasr7D+F9IdkwhPhstMa7h7U9Z4LRjiclB -+L0RuK42rHVCBQ5InMxnzzpmBz6+WeOXZhBjK4A2xNTDifUgtd9xAv5nlOXNLANT -OE14kuOo+It/5lgadF/dM1Zd2xbRh0ArzqDeYur0NiPSXYTItV4MSX+91aJygPqT -UFyGXVikxZ+H+yb0mPO+t2juX7VSgZ5myq2cjHEv1iiRABEBAAH+BwMCK/MLFFo4 -l3jv8/bhQFqIK6lqtzxYWKO6Wa4w3UZt/dAKic+ZvSreEXulMeyzNwH9mv2UifxO -7/S2F1epIxKnUy8lVzyjwb1+9ej9IB6D/IzV42qg6iIPX+vVXWG3lcnL5kX1wZsV -Q/8jzwAvxqg7DIXy8/0v4y7GRYd5vTHDr53aM4miKii/ehApQ2GJ4G4S+kD4ss/y -zkvhwo027g2xM5GvpQlWgG37nrYqMUFxNKmAW1hHzJGXr3wx+CNnCyZXwb/+WsQm -fy8cM+Ahm1/PGDVv3Alk4tlYs9bJZv2q3/q9vahAGKIX9uVK41dALq3C6KFdCorz -KqsONeKlp7Hk76YrsUZJbpl52+9j3Os8OLexJC9Y0M7WHpqn0RfCXJrzds0fqfmf -37rvNNYzhVgNpljxtoMu2/DI1d3a8BqlRvbq1jTUDWo3cu4rSn4KKR4qdq8CMriP -KVrXCLgOEWDrmaoFQbUWHujEIVo2jnLi2165jixZiX3JeJy+kMDQI8I94qqZ4JXL -fJ1CXF6YAMMg2cQnKs0qY7CftCNnIf9Z7KoYePVwzgN8Y8huEn8XFhpluOh8YrTR -CmcsZNoxvf6u3vnAHUaNoB4+ICf5t12XEEflBgA+wDkqFfYtKAlU7IPRG01y0oGW -cA1jzJfxSueaqSmqK36PAwZFyOpdPv+bG8QXPjORThRrpvMie9OEhPWwRj2S+IQP -7d4lic5NgQJUmCCCNjN+X0G6NOzEEEJBJ7P/cfMJlPdj7F7QVOzFJzW7diTycDsx -sthg2j2yOhaAOFHZhjgvfJmUajz3Ukm8Zki/LoXwY/lTv6VKZ+LrNImndn8TcsEd -yJ96t9QYx971cwDMofW0v++hWtBkk0kkr/2L9Mp8VVal6DxFfIyNEuzgxGw283oS -OdgJFux/PZfRYQooFLqviQE2BBgBCAAgAhsMFiEEvVU1sclr8JFJmuNc9EUZXjDs -XUkFAlyH460ACgkQ9EUZXjDsXUm5UQf/UZU+ejtFyexP1USOyBg5C8Wes/3Ps3f8 -n0WF7i5Et7OADyPCney8prNhEIe0DFJWPAFyucwbPQbqReaoBsxHby/tsQNNOT/K -Eo2atiGGDU/RfHR+LDehG/bAF/ucDnS/wkddDzpYz28Y+3VKEQLZGGluHLGgqp6c -YgoCReHKNQHTrGtZjkbwV7CF9JrB7kNHIrfDSGB3PwVam4wPqz4r1VoxrfVN/uIV -pOp5SYfmFdK80t6DiIU5FgJP/ET46p6+PbTEULgd7+xYmeRPzvMfflXqHaTAevPc -GmdUJNt2OQZgBH60jM0wH7sG8q5H5p+yUIqj4UhZTuGyDHYWviFk4w== -=hIyJ +lQPGBGFe764BCAC4N4XxamePdrIWL9xaXn7Ob5DTd1Q7pJWly8sNkbqfgu3qV7vH +gqloU9UurJE7GqTI8zqJntLA/tZxxBlzEjOeAsr9fO72+Mtsg1QOf77la4QMxTWb +G9rFgPKB+vU8bMQDoYxXzRIMP1iWnQcaoHGZSNSyXBQvI5mFC0xdW3mLRDxqAabg +EY/gMLyyR6iQjEN9XJJ0oCNUAoXL5mT77WPkJCmiaCo68UO9ldEnjy+pz0R6X+zu +n6Eh507PcBg5iMlx2XQe1cbZl3OvURy+/3bRUoCwZNeyU4JcDSQGlo15Whyo7PGF +snGLQVZz2mPI6uBe71Kyq8DqvLxnTeu50n5nABEBAAH+BwMCUVlkuLNsLbLzMpiJ +4FogsKmylepAWjKL5TgHk9wLXlNVJrtzmmnHuNo/1q9XxRKcPun7ElW5wdlAHt0m +4I5Ow94lZYJg+Zc/0fQcQsL2oMpfprgA3Iju1uVQesiUFXPgKEP99pmeDnGJeKu+ +DC4n4mkoJL5p8HOlp9bpVj7cUYkG6jrbLyi1ufMVhnzcJbvIubWRfFM41u7JeC1X +rR1orh2xNpE23oEh5F2PQ/gCyk2ihPI31uQM1e+BemXNudFW9UXoWpTA/BSeEIt2 +sI3fI4voU3Ez3K5UOfNnY3J7/TsnXOSqjUOdaaFgBUJzydiX8aUSPvYvlNwVlqaX +MUEKaDzQVHHPRXMBVUnmLxply38ydPVFTOWpTofoB7qtefhCanDIBVoXwRNGx0Wt +bFjusBdOiu3mfwn+pr0mh4gq9MqbX063hx8yBQalN9bJgwRys3xMgqfSbsmtdfkT +A/abIsi/SyKPIKMF/pJMQppd9lv6DvdNzo+jnM5dYAdOzvLgqQMi6gZFQ/bK96zi +FnUoPhozKZAk9CZYCd+MYZWdC8MbeKl4tp0DMe0icHZqScHnaHbccST2vWlCB98J +Y0/+4OfHS6TzzcPlaJ2KdLQKQFGDJkEUs7v3mdkQugmejTQJbMSv84KV8091Mqmf +JHwCR2JmbDfo2LPlnQoS0NId67xeqhlIeCtBGXY9dFLXnfy7ygHv77Z3O5GlHuix +hj47oC/g1TY8ppe8m43sdXcsbGFuJDHDHPA8Auyu63nVKtSVfmRn3Gp3f9Hct10f +Val35JoIazkJtwAx6XjPz/QhLCEjkQ4f28EketpmMwUtJXERhk/a9ArWzu9lIl8R +LAgpe2dpbCnm9gLHGXuO3nvnUhzcgGxSlXZ1msXM6rrBNu9vRzk3lRk5RI1U0bz1 +onUz9B2lItRbtDBUZXN0IFRlc3RvdmljaCA8R251UEdfcnNhXzIwNDhfMjA0OEBl +eGFtcGxlLmNvbT6JAUgEEwEIADIWIQSgH+x1hw3fAbVL13s7vL/Xwkm7cAUCYV7v +rgIbIwILCQUVCAkKAgIWAgIeBQIXgAAKCRA7vL/Xwkm7cM6nB/9p5FPi7cEN9dm/ +f3RUqZrHkuVdI6nk6W57x5UKn405h8Ux6vBdSv2vjjhhQydB/np4g+SDt+LUlu2S +3wQlTCQRD1TCPCmd1vIvLjCPfRQNMOUUlAZ6LZj1EmZrsbgCPClZX6dRuNuPR4zP +/pHjvx9T+hUuvLc0PuiSuF2Y2AGuwihiMC0VdLYdo8c/5TkB6som1knhRoUw3YQZ +yeOkOaCWMJBxeEEwp49w4TYBofD3eQlK2zMSKsjz4c9hWBCI0Uzd2MZf590rimBU +7t6NQs2UCy+oOCAgVY76qy5ytZzWlendBg5lX9U6PPM/xnRJ7jNH/DsbbAB8Gztc +iZ5PK5cBnQPGBGFe764BCADCban/btQheW4qVr2QRsam2MWYs/4AY7/ethTt2WVs +p4sGtAMulqoGzKXAFuWjub/UoevE0z0PmIRjVvOGY2c+eLbKCahp5oZu+N81wj71 +iC5XSbmz5Ka01EpORGtGGfYx01KU/dkb0qYWfZiAw9xurJQwbIN/9A+YENnZxYNz +nEE2qnIrpuDXmPsYwz82XmzXyLQOrBSeHMJAJKiq6gLKPeBMwwRrQL61ZqJGAHnA +2dJfh1ggtExkLfTni8ki4C7XEV0JsiU/artGw7ASQxbi4wOV7sOGK/UqfsItj56o +XE+b2JzEfd4jRhSllp3FZ/QTrxDLUnuMrcC/fBNISr97ABEBAAH+BwMCOuHtDwUq +w4jzRVA0fY9BHfJUadkq4KSz63Q7iRj36cdVZQ9ehnM1d23/+SPIOrPfRZOICUkD +KhD9PuHI+MO1in/AUWmXmduhGzWC8DDn6lMeK2hs3ohZ+Qe2ozV9ApOH2aBJXp4+ +75oka7YTYkoMZkW0gxyODloMhyP5Zqj7gSpjOxI0UUHJj/T14QeiFg9hEB2vTN74 +JoCoaQwkPhBVP3D75AhPUrM35Bs5iey3Je7uSLU2O7EItkZpeMZCX+ipdyVKS2SA +PJiM+4QPFyukDuRTj1MqrW19DGQsnZt/nu2CyFLQe53kSsfNyblRjRajudgPfNuG ++yJCkShmq2K/1i4DKG16l4gbtKuCtfgNhxhf8Jp4rwwbO8+KT3LTPi58QcLL+90f +oj4ipfAw7qWJuwutEG9+tPzcIisnDmum5PriwDPCcrXxi+HK/4f1rET4OSQdP4Fd +2/V5pobIcUZv/fweyEyqZN8MC1F1SsQQldg/8j3XkAImVdbecl4RXDohJ5yy/E8K +iyMe1LJwvQtbNjEdBDCOgOKYKg9UojrlUWBxwQZl4NLy11RNBgQDY6lKcypI7j1g +krDHPVEoxewPzz7PQGgeDhSmM93kjKQzU4vmZrIub0bnOkxrTOz/1UH7NkH5RZpL +vMjMKlRCeEA2+Ccq4ijscHYylwq41UKoSzBsM2mbK6YrrmnBhhiysuel3KuwxkgY +SyvYP1kn8G3hamNzxCe3Q62JHiNkeU7EJ9t++eMGumSZAOoE2Bourx8yHwYGdbr+ +97oIBsyRKfrixC5fmFwp5oaT7y+9fW3/0oU+meKwKV/KoBVZZmueQa5zo18iQNMH +xALDGZ4dJtDFACaeveF8lZ/8rRWcQBDdKThlSvdlxXTJZUyYz4PH+9PSRSwPFh85 +RmRRF4wyu9TqLAcfBOMJiQE2BBgBCAAgFiEEoB/sdYcN3wG1S9d7O7y/18JJu3AF +AmFe764CGwwACgkQO7y/18JJu3DGQwf/RFg5kHrb/q/tYc9PPUIQaBqi7c7AlUv8 +8FyGwPUrn1Dib9FJUPgFhwpW0j6dtazDUqNGqmlxpGuKgFk6pL/7NMPSw6kP8pHY +yU1/mcbL6TrQHlMssxAs6rVi/gQw8ydQpYdCkf2gpqY8n4Qn9d/rARQTXrbYM6v7 +76TP0e5ZwHohem3eMBAeuX20Ilchbc2LZrWMe2KmXOq9cx+H+ZSuiLqJMu0hhemm +qJ1iInLWBuQ7LzYQhzUkC0LzqwujYxyE0x/R+TzhW1f5IZtciHiR7++czU7hqlsr +BV155v1z8JpLUakEvtSxlIyCNOjnF3JxydJbJgtUq3QIbquM86C3KQ== +=iOlL -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072-sec.gpg 2022-04-15 07:49:22.000000000 +0000 @@ -1,83 +1,83 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQWGBFqb+fsBDADPyhRPrLGrEKdj3uxZH7TT2CcC9Tx7BDsB0XQ5dB5Wlj0UCFcw -gIfD4m8SYhdr5gOkYhRtlci3yChClJ9u1AWRIaTHZz9OuY0uLsTYUWwE8a8Md1Yd -aXEnvT9PXBQq1lBbSwJaN+h5k2fsChSzFkrI3tUhwbereZDQ363kIclrHakjNjOI -4iNBIBGb+oOeIVKJ+t63VJK59TQqCJapcFGEPdQItFrhN4VccMBTHUvWuc5h2Ku1 -VgxfZCfcb8UWkVU47hZ+FXh6gQHH43ShEFBhkhMOK700GfmAlJ3kS8t3l6JPf8TV -ZfivTMMkWo5XBlp1Yn6exQsVJ8ue6043HAP1CjJ9qIDZkHpVhX8SenYetMVRHIfN -9oWiATct2x+w0p5lDpXm0t+eb8tl8IHo6K4oY4KcV6MALHL9H1EAbskJuH/sodiH -lGlQkSAQA+xyYu4NX0p59H0p66KzpfBm/847+dtohwikZLDrAPHGFcFKQn6QE1Gw -2Qqt6NdtDXyVD3sAEQEAAf4HAwJ2R4ukUm2flO6otOI6/1R9hF25bBr2AojEFcV/ -ohVQ3eqqyxY/9rz8CsIZlqimXq7An0PVMkhC6nkChxAS6moBJ79IvtmHYs0K87wn -BL8jCuikRKpaFTjcsnWQXcM4slUmyrTOGQEkDzrKg2odD6vB14MhCgmA7k52Hl8u -BCHvlPXsScg+bOzX/ZHsjnDFhFg/6bEo6nW4epCA5kG/h2x91zx/6aZdIzL5frVg -MD9X+u8D+75KJb6Dh3uWCR1gtf7eBj1VdKjoOdpOT33WaGG6uX2/B7Xu8ok7ujjI -FdP7q3Pop6TuFcaaMz0dqaz7698PfhFXbrSpiDo2PFxC4Sdw1ZMFw5WBov7UJWjI -2Qp5+l0/gGrN2+P54M7B8141QNXp8DieRmUe+qsCfBa7+pj2FfgSPUm4FGJHq5Lg -b6kOyoCQ7kht63prX5kmoY7/pLm7q7GMHPTbiGHPjdM2EDd2m+L5TwAgX/4FBGMp -6qQfN++lY2mw5luDYZPrLC1HfTNRjGclUzb7k7HknOiWVJtCVmNZwM/atTJ7LlCd -T/b2mVA5qcYOAasWTix/BRiks4okZcU3BvI21ImMklO8+K2ctczhJQ2H9ml9fpJb -wAvbIsCn9p1JGkJeQDXeAACdbY7lDMLuqsqWY0YYe5frHcVlYNzjx7W26WkbtRCZ -eNmxMeXJ0N4baOTEnATafZGEdpvio1wILTkRj+4cnG19Im+7tcImL7lV3SkJaC4r -bakD3fKyM9WqBdluhoDPbFtEqd0sTsiQKh6K3PXKZn1eaOGHNpwGERmef4Chk6Sw -cHgMrSMNvPTC2VY/jpUZAw+BV05iB7uIj7oQQyRpbU1GY4/HQ9gfAOzHnpVh0Ms4 -+kGUrWZyQsZk4MEyKApKgWxDgRS9ApQzVmUJx3eRgnk25+o3qp+591F+BSJ+2E0p -qd7jrmRHoJvQdBzxQ91u02Is0QUJGG3y9sJsOiUuhUlYNc1+SerXQ7ebJhqRq3ia -UZLQLx9HJHaPV30b4dPbsdrnlQYJ9OU44N7qcks/ae5M9t174d6a32VNKaDHUkb8 -7ERD6JaYwfN++ytOrFi6MRUnxJHpexVwCydcfWeQO38xfTPf39i1VcnyODotumHx -gytfVSuRv8ndqCm17gOSQ4IeGW9B7ayiZmSNxV/GjFoFW67eHCJ690/IbQciUyWv -KJoBTFt+5/1TlQP9K3ZgrMIloGHDXETUTHL+Zq6EjpFxqZwo9HXsKHPR1uPwGYFi -FKHJuIeIOKQedy0qiWpdBt1Zp4awmk9ge2hNG8I57btNxcwKQBAbov9Th1Qxifto -NHugcGa4nbg2WJT7o7lmGSbRYxcfFO9uerQwVGVzdCBUZXN0b3ZpY2ggPEdudVBH -X3JzYV8zMDcyXzMwNzJAZXhhbXBsZS5jb20+iQHIBBMBCAAyAhsjAgsKBRUICQoC -AhYCAh4BAheAFiEEwn4pA9W6SOpabVYYdOfouNGsbqsFAlyH464ACgkQdOfouNGs -bqvlZAv+P6n832vbqXGUllrAc7WzWdB1mWWp4yhXcJvNfNr7sUHUeJMxh1A8RiGT -YSTTwsG+huPP+x+Wb8nNcWAhcWKnBwYnsOgF/qp7FOSfH99CHIo1uZQ/0MjT3qAH -5Xwuv/sM6E3OUAbLwUCWlT7r+a5D83Dqdk/vRNWFC+vA4c/UnrdXMlCyIif9Zqgo -M3kTXcGHMHy+jUimVVEZiPYYVVTQ1Nm3Rl8U1/aKYTBdB/t30QJREvyi8pOk51tb -CkeJiX966Ge2LE2X4TbjzLkxZXL2XpNlfii3jCnrEwMSsfM49S5bbzc5uRjNj1N+ -ozw22xZPR6KT5mvlGx7HX0lC0UrBWwoT06PnNdufMsCGBuq1MRwepuoj8LgummdM -hLFxf+cXBNcAQYYUuqmKyvmg/LW8J13CZkayEX5fGo9njsv4AAdUqhXeF9XFkJJz -/BW2by/Tuh/O99eWXx6OCu9XpPAmAU61G2omJtSFaUFChmO4OHe5sCjFK3vN0x/K -ate0jKaTnQWGBFqb+fsBDADJl8uZfFLR5kJHde+Mm4d7FQuC9Qlp6mB6KfP73TfT -yV+KX5CQ7khdSALs9y0b3xRHEWCW8Vu/DCGSKGzPp9cC5s4vo0pigFZTJ0mrQiHT -gYCpCwYtExEfza/rkHXN4F0yeD6Y4gw/06BUjzbKIWM3c2gEAps3Jv9M/tSp7oZz -dsTtm8k5R0ReUqYilYCjfxAyMMc0ZgGmd5V2g8dRzcNu24zfyPrmBDVNP4dIlIAa -UTpjkn0YyKpC/8/RdRVNMsmLJWAb3xoZKMwSSYNRsSWPL8c2yTHoOYRCPX21vGgK -LsyLLu28CLTRtwN4tEWl5SFgDTddObtIcAWcEiyX6/HQz310fphDBnhTUTuXU2S8 -e3uKtPoNUexGRFnvqLojXQzBt1Io0zvd209c1ekCW6BxmQ4F03KnjEKL/dXDK0fy -J8bzuQDNhELMQ2JaLmrO3Y1kO8VPZtw1OunPcIcSxT3vWAdHSsj+w4pEAcYdMhta -PlNIn36QM7D7xm1vIS2ip/UAEQEAAf4HAwLMxqOPBVxOnO6TamTjbG4eIP8dcMct -L/+sBh5886anhnOJztGYTm8UDXRz01Yxo/v2P70NxRB+rrbKzVL+xx58VZ4Ufeo+ -HIZFn4lMzxXVBC2QEcD7loND6tGnZIEJYq0zwyo26GU0UNAguP8pqriDbFJ0mKqj -IE5Rx7RjJ78YTV4qZRdDFuCR1KcEmlURkowdep7odb0N/eJk1tuUwdINGXcZfWy8 -iL9m8fgLF4gKtFzab9bHhPhmF7ObiFdoB7d3JntDapUGCFfXmCCRWzHQclrlr0L3 -mpUGXBrJRBDUJlE5oKBtZAQu+5iRFhdX9097InwH8sxRVGlG5gwPNmCDYv1woqdC -8JAoceVF3UbzZAUzk8buMhVs8EPISghCbALeipOSsFxgRLo4R33+thPlI5EEEWc9 -mra3/24pAumc8uogBX+mDeEBufh9BXGuqOvQIu+DG8W2i9sSXcvBNagGAQiw5pMO -cwPGEhPsHAKp5nCRpPEiHH3s0RI+Sd93RMcixhevWTeaz4VIVfo3txh8Fw0sEzOF -pYaKVmhVcI4vjjpaYhMJrjfmgLC4nh9gVBHjy1AtT7H6OHNMuwtUPiUIDxrHkq8P -sGqV5lgW8adaZ63bd7BYBFLYMk1yhk6QBTtXgDCJZDRD7xpFYhZjbk9ET1HABC/f -cfduiRCPsCHKyorldWaMhs+j946V+rUIk/bI2rjOeV+hzeE6nbuh0CUkuXJR8mqo -2v+y4CXXzQ69wd2aHY4oinv990Dpj+Mzap4VTNxLWVhk1uYYkl04n3pvCZIDZFXV -pMIf4dogdTAYaFhGztxAAI65DocEL8hmRLPj5RLz+ffxhH3NOZXU4Ddx42eDlrhw -56DABWGdqhrUF8GhykaIbPYkNiZdfhp8ifPAjYanCbhGIMHfDOH4/L6morHdgjoz -6PiOF51V8ksL/M/6w5Pmd03RQr21i8U2iruTwp4oRVp2A1vMNzYhiwfrrBMXtPD8 -MuUyFtfFqGY39gdOhv/XE0oPmzHoOMYE8yft7bnR6SwcPd+C1eANl2EFzBm4/CAM -Q4C8HWF49/wX7Ca1bDD9A8IQd/eJL0YnVzvOsjMABDkzpmMYWnT9mmPYaQkH2+A9 -Of1TQr8FBuvtF5/3wL4IoBfjh5zvqfTELolXjmuNyNWfQ6C/GRgOAjiptvyVz9/G -i0sFXWf8OpD6Itxz34ugn4rx5OPAPsHNxTs4M4XnUuz5o5rx0rCt0i5TpmCd+pZW -kFMosz0YyNZjTWWQIZP47RM/S1ihKIzCx5LpNNyrQ1ZJbEHMKfOWXDkxxOJQpRht -pCYiSiH414je3pZP3+NVfKtYnd+eUD1uR+KnLbX5ZIkBtgQYAQgAIAIbDBYhBMJ+ -KQPVukjqWm1WGHTn6LjRrG6rBQJch+OuAAoJEHTn6LjRrG6rGBQL/3b+sPJ+Oyiu -goCRaUFC+vCZ+fhfYX/dfhOZYZIWmwGttNXCcykYDbdl9PR3v+Lm76iW7NchroBV -m/oBVoWS1UtZj3qhiJqj/VmN95tKk+892hPeqx/S9gRR6u0CD2kQ6nccVdd7Gjt9 -wZaCRmIXMVLjU6r57VH8DNuElJI8/IcF86+AOlhUERqm3NzhPyE4s1nV+gsslnJ2 -BTEVtvcbug52yy5OtKxbbydm6tfz+zy2XYOwbhTHiUZl6FFeomkjTlyXhPWnwfPh -M4vfup2tLw6dEWRej1ZmJRwDtr6PlWwcWowfmPXSoprsMd8h5ABe3oclmK5kJfJw -aL4+6FdGLqJEVML6+ALFMm5WfWH/D+VMw1MJhhtkUUBr9in0UUqZC1nwcexBm5Fy -bGp7yG3rOi9w7mvnOiHCV841f9Uhmw8ZpCjbblc1iPVUKBbM/LmEbS3zE/zNM5nl -cg1RBopJrQb1eUQXq/f/Q4J3y01X3wxZPhGlZOi4d0Th85GrD+oP+g== -=194T +lQWGBGFe768BDADPlmdU7SVX5aISuXZh6iusG+jh5yK3rjrOxIjgb910G3wdvqWV +S9Ydcp5bUZLjc3R+JdIx8EtrwVVA/zh83QhffOYD76sOzp+ow1GuuN4PIFWbGKIP +9G5OFA/Wm/4TV0ctBlCV6vtr0fbLlFTxn/dNbIQeid9ddA1vYhjUfDpSH8I+tzGr +FLLYQdC2O1mvSdbSBtLKUwKAvY5A414AhgHcMZGwxdACbIKeuNeWe189PFvFV7hH +q68rl92I+ufdv3QqDDPIs1QHGFu/iQK595ma26d2ETCw2YOjLmxasO7s+mu2i/yD +Tx1AD8tDluA4XC42xjuhtsMZ/lCTta2E5cAeUdZAkvoxnlI/2VBnc36b9qSJT8lE +Yaf3b9juzNwIqtTxX3biBfjcs18qtwaxbKMvG6zf+HhCKjLjEXeg4AU9klap/Qas +Si0acrgo3DHWtReP5UOHXARmefmae1heR6P8gg0+42qj+RsH+0mx+WPRJgjHqzz9 +Y8ksrxZl8kTtRkcAEQEAAf4HAwJyl4dmgkxhWfOTH5WMwdfElXcr8jCywMjpKNs1 +7+LDJcFrM/2V5YtfbiUDtVIv2zTpW1sGGNWA7sOR8itSpP8TnbcRxOBXC+hKtiwr +xkGan8X4uy+QwVHLOMEMm+Z1F4wr+X3gUADvwTrsnenuShbwdzF7N27KzeQkfKmd +dlgkM24cc2uIiCRWWtSu164yyLYBDa0kefrbpceO7kel9T0eWotsYsmA4xsVOf8i +lC4XHiSB3oJe0CbXqkF2jW5BGNKGsm+P+nF3A9MrvHrpzVEoQpA/jv7KNuZNyM6/ +NnhB365SnRJdYu1rmUWrEtXpZWcvwHJdrdVB4J0Ymaqq4AI83iVr4CKwG60KlZ+7 +rGIB/pNI12LYK92wSB+w2nJm+5wEvCwXO7aSAnRfHbhagzg4S3U4T8paU04XqqyS +93kx7+6ss1WPSZhtXrx7cDYGv1eHaqgTxO8lziKGVwE6zF4H9Wo8UoXw/ganvUFL +VOTNpEzC5b4QELaZxzbpXBPAxfxO0nSfrp3q7lVqW3jApIATRyPOhwDZg5X48h8L +iMBQwj85XssJwzZXIBhEE4CZZN9fd6S9TLa6IC+m6mbzxRqXNXEhiv0oV/wjbcx/ +xhtzznyiKwGHwefFHJeDy1hS5nR6LP/MNppL9+6gzUhHg5auwvt4cplFOr9NwSAn +IfMmHHyiB9J69ZIN2nnERoME1zMTBSRKiRYf70NhNi3M7W393UUl6QX3LP7F7+14 +uR3rxJC3a6Cb++Jl3Ly2R3Zo0l1bsHet7iWeobvafkqeMb5zks7BlPHmoZHDyKg2 +RP7YfK6oERTglZYk3wcwdV8utNN3Yva8Sy0AZco/c4fDTcAnJiIpIdSZxpTwbF0G +1+0oBHcLgu4bABBwzhNc7BM6HEQjqDlia862ap8GN26mXra0SL1bvVCEhURRCDn/ +XnEInG75jYb8h9lhxippAAGm/y0Ok5nRVge9Q2/sxD+A3CtFOuK4bhYM9dm9BgDu +6FshYA8XidKyG+us12d7cT9u0Ybvnj8dl6Eg+Eq5paULCmd7vdNpPlApEMwxgeAp +RbrPn0qZarPMwX+Ttz7YwDz9y3je/t8LEFPnKTu9HqCsxZDqAiaqKXvSSKoR4Sgm +4kA9o+LJxkGPboLYSjepZck+XQ54cvriW/sdtAcV8XvwDIKDOiB7ruCZLDwexlmH +5ImhqpZ2ZpWo2a6tp8F3MreXlGfgKBuKucEyYEAiTZ6QUMD1gNfo2mQly36jmvIf +vQQBtGQDF8hbF4muddoch6VwzNBL7Y/Mgo4k505nXotu+g+tNhhc9WsOduK+RElb +PjBJoIYcq52psvJIlEHQ5ZnaMuw1aBQ1ubQwVGVzdCBUZXN0b3ZpY2ggPEdudVBH +X3JzYV8zMDcyXzMwNzJAZXhhbXBsZS5jb20+iQHIBBMBCAAyFiEE28UwWNS2P7Rz +tIp9u3QxK/H+Z6oFAmFe768CGyMCCwkFFQgJCgICFgICHgUCF4AACgkQu3QxK/H+ +Z6rHGwv/eP23qEVLmWF5pjcB6RxqeDVAcXcA4GsYSSPt79ZuO2gbxKqWTFTjKbwq +eEIpdbVUMwPD5O81web0R+UCnOQIHM0iSPDTeWNGMhakI4qG7aM3qJkQFJ5zC0ok +eswydqq0Dr5lJPro7PwQyh8T6dJ7wHgUV19akwbL5ESjhr2RYQJFRDk1EPfR9d/+ +BMR8nBDt8xPkXpJthD1wVrdbV4WjTvXnSlA6VAsWRRZpDNpGz6nWl0eMB1vsyHZ6 +LcXdQK58A5yNsDde2V81oH7+uL45ZB12nmJUp2qu85RN8sJkJJWOm925k870DMdm +bgX64D78t0fndYc6fl+0Jj+hfYoRapDHuv9+16G9gxU03qyIUcQ3ggfJFRrobrGu +Se/AT+jnuaJgBkUida8JynIC7Fe9A4+KWc1KjyrmxUPySnsJLMI6pgRocEA+iEKy +8UCrkKJPxhRwr2YPVzlbqI2NotZCF9b6u2TX73Un6oQdGE3dG/DyM4k0MtqyolUR +fJANxN+EnQWGBGFe768BDADH1ca1x+rCagLAhoKHJnrPSOHxq3mieMyXPL+3exk6 +gqWdaz8XQrDKvQ9ZVMV6LIeSPdqEpT/4Sfu+ImedfLQWaQTedOLRszmrTu4Llrr9 +iyoOuE3yQvHQUEcZ8MG4a5zDYnEMKTkYnIXQFfwWvvUFT1DoEftCQfuz18CktyA2 +FGSWCrDp9yP8bcUpgy+B1bvTbchKeNgjsiNz1HhInzS+ZMFTFsAv2xjoRuIbeh8z +2IHE2JXfeMbqHDPn7a5oZEY5zNc63cS+dLdQoJrgig4AEYcUDy556qmQADFwnsJ3 +JseiVurBJI1sC8rpk5FAbNCoRJrCzBVTeBhU4gK48Mph0PQDFFMS+cr6BXN70lRi +SKzDaS3nWD0YU3aQhyxd+01NoN0PstdHmixQP9WIPuS8vSJRE06Ao5THbfL8gZ+r +gw1a7hPyeHhoDFjA3LK5b7e507yChZLRrmGLi4IN62etBnRYBcqPG2hYC0Q9F79e +rlzlTfMX57cg7pYjd3FaYosAEQEAAf4HAwIKRwl2nGn2FPO1z353ap6WYmKItJGE +T6YU7aLLdWyGU0ARsldAxzsYpCpK5FuGkgzn6oivjetNwoeyihZukCbBImuU+IWj +G5E2+bODqYHSUm7Rqw4vstYEQfZMfVjfxU41280SXOvVNYD5oCCtXHBvVKr5OWHi +jmMuCf4YcVY+JgqM06dd1LVctKIvwAZkNCfP3BpCaA9Dm16Slu/S8cuIvT5UG6xy +2oWR6nHV8iAMGGeKrUog9INEfmC9/6f3K9KCiXewWBaV/EOVND5tOECWaI9DHHKn +LlnDRKFzQPAmQXJFLU90SSE3bE6XiuMY2pGNm2/3SN6lCZV+KFLy0Zz87+ANF6nv +5BsYAcLFlssHEhkWgwiYoKRN/uYD4eOoqFH3NX2YieA3Onps0pm2B69wNSbJwHAa +pKlsKtoW3tmPOQPqQFZr6Nisv8gSYirRNtB4wEdedPjYFaqX+u1JZD8bWP5nNy8z +TVqTh5Yq7naXKojP8cFowBTE3K/iFIDbEUJEzf8zPDoi32WV5l2CWt//SeyymClL +c0ngN8kd7++1+cwYHH+sAK/qge/g7zG0nB8372yJDttETLMyYySd1XwfV58eXQK2 +I/9bBkN3AwTZTBWErnt4/qyGKaYzlNnbqMK7Tj2MM7vqNBdf9PtyvcTJGTV4A4Pz +rBtoYSz7hJsQ4Gkn0gPl3hxPKgH5u3maqLDWt7h2lbM8yg87wlXa/HouaInQH/48 +kuc+tst0LAleriPSih9KCUvi5GRPXhcvTnItFvIuIibAQmTQM3tsbjEDX5qjR5vA +6rBh/NYrDer5y6m7xidwmC8wfIdy+LCd/Lz+wYBCQllBGSbtqZTbNnmnNIj4GTfr +oAumrUvZ50SuwTYpTn2nwLkRlIh2mJul5numchZX5YsuKfX9j5P0db71Aq/8ISwf +hIVh4Ic6Jg2cbxFsGKs1HVEdL39s0FieuBAi3qd8AX19+RRdTBtz+pypwaGwIwaI +FP3IATNt6EZE3sf8qYXSOnAl0jdhbcAc2EO2xUyzI+iHJxy0uag8ncbW29Yf6LNY +tfrn6Ymhl8M6xUfpwil3Xj0AFGmjLIM9VAXwXpbo9SIm/KYUjIeGM/PJ4bGMRhNZ +3y9jmzahu8RI/ox+qhuJSnBWoqXhK7E4G8hIqpeb1kGeZ+seTCPvh7k0tBIuW3Ln +XU1gQy2IRHMvVQve0lXhk1z/GFDwL0BnGzeTlROZ0PUubNsxVb0/cRq+zZ7E82cx +mq7XTlpxc0JMaPrYk1vmlqP9I63XnKjdppepcUOlkbNAV1RhVZsPn83nqK0Hleby +Ekda8BD+Wwnn9FEOJZoX1N/+K0dB40FxCJfmLBV0eIkBtgQYAQgAIBYhBNvFMFjU +tj+0c7SKfbt0MSvx/meqBQJhXu+vAhsMAAoJELt0MSvx/meq9cwMAKXxOG0vc4Gn +aOkwcWTgO0guWM3lwKeimAeoCGEUW31wqV0GtUM7nGOOmPOr6KMCr0uut4tVhkf4 +bolnfuCdRnsB2TqJxXcmD6Dp+bxl6nFna8thnSE11vTL7h9KBxpnycNibpHwJjOC +MWa5+2xY5bbRqvoyNbq8n5kc3N20KK5m4N3HUIyzgY+C0U+Tu4IbI4+BiPpRdUp9 +SOY0q7sFTKvWdTIkGplTCDYMhjPoeMlpduZS1a43+vZWbkxxE9hDZ9UQQsarm21c +JHlakFQ3KEMQmnWNolTDrWyGohU8aHqDyjCSIbCw5VZp/idYfLbfJng03xsPayGo +AVdWRjfIRGRWg+lsssYxs6JEBzaykDQx2nz7iHLmAzvxjLpWNvoQaNgFPrKC5z69 +uuzwFaH1/LdpvIuQG/BI0Fh8MrJAYjr2rp86wY7X1qoRkBJlKhlCblJPikiUzllG +5vndiR42WGaVFyCIEy2AtdomfZqE/fYinLgiTaH/nBrvFg5IcmHU0Q== +=uNhW -----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096.gpg differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096-sec.gpg thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096-sec.gpg --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096-sec.gpg 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096-sec.gpg 2022-04-15 07:49:21.000000000 +0000 @@ -1,107 +1,107 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- -lQdGBFqb+lQBEADWGTPH/M6nMxIKLllIPEqFaVjLl7gyExKDYy9Yr02qYbSgRxTf -BaJ2ED8+2gtZm8KMtyaxmYXd/bm1/4fRuroIULveqA4wSg/wWa/bBa7Y3x9dJltV -+hOOrdzAmumhdBz4AjwuPo5e7f2zZj555pi0aZVF6JA2xQHPLREM/pXxlByLXzsO -BAl4OsGDqnLTq4HnE0ujAbLqgt/8XVQ8xobD1Xw+MQdoFot2Tb+li6V57d9HJGur -ssFdXDF7K63YhXKpJ9Mx+8Hw+akZ137Dmz/HrcY8FLZd7I/lpc08CmPJpzYbz8Pp -pBJNXnSlk3XuCsmGiGq8nVz6hJjeNvwukekAWmxKfaJimjrsBFFptQ7SXuSYCaqj -TJaqsdYIqgf9ogu/V+5+E+0TXcy33EohQz+LIEGEZUM1GjI0WlE0yce+OoT7yD5w -/gog+UI3PUDy6/dl87dOrHfmRF94m9c/HQ/mR+a/Ju3QfmjvY5iQztC2rktbj2Qp -GYCaVfxjcQK4Up1n2NoIR7lIbORar/usdyjAx2n/+oRdbl+wLuimgXOiz1trB71L -/QIyQHuhy0riNJ9LEp8ch2vHI29nOxj58JrerGudoeyeanOaNoUVjJxdpqM2yXS1 -mefgkNL0+lah7FUr2JT3sO9xaKmr7AwCVGvwmgP3mkmW5xJssOLEGFnLBQARAQAB -/gcDAu3O8XJ7LK/D7syLvvJQX6aly283qZQIHHLjIrpIBDBcDvppn/ecWNrtUVU5 -eNqyvTDWW5dIqbLO9M5akRl5qD0QGyzb7yUAurD3UxiuWe20ysxQk4EdoM+lR4NI -8fjG9I3Por0/ueQI7yS0iwpIx0NSD1ChOFtC3NamYeD85jKoa0yYdzDAzObi2R+Z -v6dCPfd+7An+q7D45VqC38f3mBprmhfv1tBZeyBH+Skw05BEFCKkTGmgalVtKg7d -m8ScSwNSly0x6GzRVUnskPZUT3q4TseBG1QmZ8L6cmqGSzQScCQhNgJ41wgAf8T3 -ZryR2izwj5Lsi6i6nxJq+DJfh6m/HMq23Z1j9UFBePXnNtawCd2BI27wPLYlmULb -dDmv/KFMGMcBwJoH5BN0dG0pmNlMX7JF/yDRG72lWgSOarB62ZL2Fq8nJJ+afsfA -0D02uAV9eNRwfrZZHnMrmujhQ/hHUKazn7RAIW9mfdyax17cnPKEFwMNKtIv0tCg -cxD0oDCgnmuadv0AJrNftHX3+cdM6B9dJpNksel+VA9GlUHUshd2L0vCnCUR9VUf -SMOZGSCK+NW1E8ys7T8uBwyfko65Zw2uCb/VIG+mC6yEKb1OsULLjC3DGuOGrpcG -yM8tzTgTCVhrZBeuS3vuqFg4LMKeXx3mUaWesw9VJdOdnMx1bklfod7ubIr2093t -s5J6/lp0qKZjyoinlRTPUTZo+5fLP/S511lcld2SMLP3/hol1I44iddR8AVslgKy -u3h7AG4hyjRlXw1PyIXT7ykaMaonLtTv3dUqUEpoVIr55jdJSJ5gSUxLmRq96Zj0 -QjcvspUEKP7047YffdTmo8MtXwcWgEhGEZgLH5lRZmugv2I4fCwCdRC6rgMaHyBE -3U95mCA+dHsBrLA2XDlgJ+1wRn+/GVq1iOLmjH4SVBnshA0Jor9VERk33h77i2Ea -RRBmoQV8pz3MYFw0hkna8ejtvDcdasbAt+48rCZTfdqDWyIBKkjnPo9fVTTBaIut -yp/PgWUu3YjqtC2u3ZfVYcRMFkPwg5iB/GJ9D3Yn0BZ57Sir/D3Avq6lO3OmGPrg -NT7PBhUBwPVoY/nM//mSFSH7N88AH11tiyDHeUvKcE5mPt5XfO7o1QMLx4RVyya+ -z4BJXBV/RCZuQSs4XuqEpKTWoi6cr/9FdtmWcRQcPEr8wG9qTiIkHmzRRAvTBnDk -rFgdtrGvrNJRX1/XpxrUqy2b/IXOshNQjr5rapxRD89gZZkGqSz/+lK5wO14jxRh -2mUseWgVl26SB/vXSq/QyZmkQOLx2UQCzj7QClqedMEfOMRxi7rHbWkYjiQepoma -zi+Q2zT5PqHCRtioXtPrTiB05wEKSBMI3ff4/0fZGmHH4Ao6joA7hpjS+SyxJuL7 -1uNFXtHk10kuHiyAPQdhQ5CQR76qlq/9slEYxe5Wagfv/0YxO3cdRs6mu/9CWidq -mlRzN3/wY/bL4WUOdJM4XIrBQZKh//IxNkqgBERZcKrKUEZZfNXfQtOT25hRmC1P -Axok99rn1FvkGtAyn7VgLlZ49qkaDQJ7gDl8izqkNjzJHjlFGozZTsa+r7Azx7h+ -2bcM99vReT7Ifmzj0usVDgEfxMSC+/iJG9wNOCkFHCzkUTKpvG/WI8w7rDZq1tJf -nB4PeOCy2rLYeO4MdIh0XcNQU86WxrN2ajUjxlTJemhhaup4YhiabIOB53HMnQXh -f72O/bwhABEC4RnvJvZEdlA/Y29via32qICo83Xim/+PC9hBOl3ArvW0MFRlc3Qg +lQdGBGFe77IBEAC05+BPM9J0GZxt0zmQ1I/Nj61k/fmvTijN6DF7fJdJJupPT5PT +SVgZVZ3sSb7xbljICjy1WHZ1WiRT3Ry2MPmDQKZV7U5nUOJMkXr8rTEQheYNeF0K +6+HIg3HQdLWOzhBlDLNX0Vc2okcZiqSF8GjVQ3Vx/6G4KQ3Kcb6JsCpXbmfmRQGy +tplwtryeWmgB0KlBTbZ3kMXCj4CtsvqU9+vK8J+wXumewDzP+Vy/w+4y/pbcXfCH +wUq1N2OM5ao1hZJ5uy0PV2mb9JUXtMfR+QZ3/7BmAwOCugzvBe3FRwzNFuq0RU99 +s9yZNckQi8af9XLDdfGhmyb4tlbRDdonKqlmrCGCzL7Kg1A8PUZNfHC70T+uQN9/ +jFUSNEVrwx/dy37dkkVDXOHQruKwhA2/920EG/7pi5+N00DOtN2wf6PKtMXecXFI +rhD9ofUf31EK9oTbcgUU6vc941ZBaLw75XLadC+nEPrI9nUrPVZnSTx13kKpEsw+ +YEvQ+20PNoxbnFF5bdhWKrgAIQpoBIOHUiAuhl/++T5vJv3T0FpoYvlYzDoprxxc +e7byVIYq8K25sO2W3lAgfn0Wu+jEas7nu7ceSAAHOQp1cqIKZY8SEmt8y2Axk1zZ +kJKkZ8liNkMEc1XNKJzmmESfvpIcPiE3gw3SWvzA+0ZKFekoHbyDJuyfWwARAQAB +/gcDAu9lw0HTInG38zE/eufyxG6iO3BLDUXYBRESbHg6Rl2OZDunUuYF/91ly2jF +DD+fJ5Ggme5tNsW0jHP5HLqsnI4GLbILNj3b+MvRUOILOvQjm48ImrqKNKMtsMmy +98lnoEET5Nxf09Wv8gDbZiHjlagGucyKFdQ40C/q8TYpA6K039Hru+nKQ/rwqKkN +bFtM7hDLgXU7CibiCBryyzm6wkJheRD6B2MAVODaoRFsj39Z/mcf8eeY0/rpgRfk +aBYaS36bjYmQs+v9AjfoM9T+l47urnhR4fnDuNX5vnHy7tWA0e22euZ+acLlvXaA +gx/UXli5ae9qOtS2UuC9Y+11VfIGwrW8ZZ4QFirHsBVZ2rzlbgpG6a4qHHDUbtY4 +BSvj0PrcXdLf4CH6AflJBnS3Cxel8DN0eWz0uNpjocYcIlGz+IooCZBCiI/2Kgb3 +qebajHKmoFl7mfHsIa6D8rI9JLuTDy4owP+ZyfRIMAPNnQXxFYNlMhC3oY5r5urS +EI1MZ7yjmaNNRNmrJ+QSFuNuJeQBvMNFrdfvXL7V66L3vHkgKMvFirFwvF4bBNuG +bqJ37lnB5GGXgA0VfHWLFSEwmK063J7YBDg1t35ODQbfUaXSfBfymIAOJgzG1Ozq +aUyV2312GDeTSLgjw5F/oCuqekHdgwAhXwHJBc1+f07KmP21gUjp0JAoOcKpPFHJ +Eh4/NLz+JfplJzL8nGfPBWHYUb5T5cc5oiEH3ctuFbsSUhaFPMYrUgDA0FBuB+BB +h2sNsS3+CIpJBHt0E+0guipjVGCtP44Ckg7qbfxKJ5ZM0XidD+CL1ewekPIg6UEs +pIJYoCsiWHwXftVdJ+7BQY0XI2NtQONiALZDOXei2dXODC+l+FXn3VGAoVAb8zyC +A1itIFYEoyvdRXVPv5ebmKaPU0mCIl9O7vJ3TQyo0b7RJXE7DDirmCRxu9LCGLcN +dWGZGtyWI9lseIBPfdvVCf/mo7wmzEaEdBDrMK1Tc1hbVnNOs3rEATJb/qkEar46 +zvnMAI9lzsGpEAnAFP9qQiMovLIcTnrmDzwRX77ldjtV8JCx92Op0dXUUAR8q7IR +92Bw+sRkLvFi00aINKICIRZubiQ7Bt4Ok5RB+Lr3qexuaIxnHq5A8zZVb9GG/r51 +QlB4sRggRjvbBMjzWaRWWUW7nVN43XsB6UB2Ew7VP6a4atEh6FWTN6to0Nh9gk5+ +mSpeH1OgCQnfPmatDYIPRKlm2B+R2Z14BAJ0B+R31nCwAxp04WifF8hR0V6XrWKA +9ZfzHGvcUG+Cc5Zq/U33FxJyZVrixLVjf4EUqAh3Km1jFHPvwS36JLZarOjGIh2B +95JI6gdUUe7Z9XbxZj9J7MvsY+em9CwPtM/zStrwmVA/glEeIFAlCgs1ptHTcjLX +9D4yTbuG5IjhWHu39XjCpo19D8TpQg1OR6CVn93q3FxGknvMQcd9hQVH/YhuGCVF +LlENdCBaRD48YfHgFPkl3IUDJOC8PCoiL47CzNiPtTnm/4+TMjfCwbcS9eX7rXIY +X36MtHxwd5aPDhkicLKxz1ZhoPaq6Q6lCeNDNrsF0OdvNge/uWbJJE1EPAXGcv/A +bEbuX/LcfqJ1hss9BpZzbnmHw6/g3HQfmCso0YZljgxOfXshDJGFp3ZZF//zTmmA +JawWrAmJwcrVk4pBH7Aa+6Psd/yVHrRWkb59xibY3BAoAZq7sDwYu0b5WWxWHjof +obql3pJhmFmxCho6yRswA2N+BAHvHtpmOoJBb+19XfAEQvml/wnLJSu0MFRlc3Qg VGVzdG92aWNoIDxHbnVQR19yc2FfNDA5Nl80MDk2QGV4YW1wbGUuY29tPokCSAQT -AQgAMgIbIwILCgUVCAkKAgIWAgIeAQIXgBYhBIwbP4jsZ16R2X6RmvUDrjWUXRcc -BQJch+OwAAoJEPUDrjWUXRccSTgP/0HmBR6IejVOCldsdCr9HhFnsjjsJjoCxTFc -OUKbUsY3uk6esLe9Rzyq+FtXKbue1gEBXZuJF+P9v2Jaq983xE4wxmXZjCgPYM2j -1ha88qiLCDrVL75iM/F0UcSsHjl6hoHxpWm7/5ilIDrcvQbXeh6AJ84wMRRq+F00 -iRNYLXenkQt3LkAeWs3zaGYOPxeB+G/jINs81F+/Spia9WzRtpV2zn/1jlo7O1kI -N792B0qDe9gazqlbg8ytCSZ+x5npyb0VcB/RXW405vjzabL7vK2qyY+IbPPeSAwE -zGPgV62SMTwgi1fIO+bRnY/Ulpxvr7G/65yK/bgAU/2P/aTwjyhOyVbAry2E94X4 -mle+7daP1vlpjE8rLnEh70eDOSBafBIgAILTJh4wLvX3puB+j8YknRnRmVKfQiyB -DNMA2iw+F4aRdJNtnuMjJ9WOhfErqKOBWhBJM4n1c3/JhDcq8igMKTds4KDRLzZJ -kkPMvycHbpc2bXag5z555L83T7DooSePpMFSWaJJylqp7L+tyPNtzRafhW/IyYEq -YvbTMaPssjkdrQwM5Ib20IC9R1r3gtg3nVTbislxm1IVG5mxW0zcjMiRDc/7su0R -qLkyizANLZHDzL/3FRmHqHkKRt4zirv/FJIw3wy0x72QiHOGRwkOYMTQwRrIXOrH -DesXfuPdnQdGBFqb+lQBEADcoNILpBNVTqGGAk5RY46w0Fj1lhbvTPX6XWk36v2n -ds1gzkMfJ9AAPJi+jY3DPNTvdFGqNGSh2yeBGfdG4A5A7vIF3rBo08UB5gl0ViHm -ekvzIWXK/O/eAqESwAoWsBQpZwDpJU4fvrol1eIlJt6dZscI7vwXnynmjJpq0piO -vX3Uk8qk1J4tc7/094dtAAUeFp/eN8UtAOjOEt5rjSCE1wavKNL+27vUTjqv/nnM -SkJ0Ls3CRGsJcptsbc5E0z3Hwd5pmtoLX+m+8h0tQkV01Fg/Jw/KPWjO9uQI3dkE -DM0NXsCuaA2ywO/rkhVDwtWwybE/iW1bsncVhwHk9WIU9Dk822PLl7ksRzlq5f4I -bcTNujicM91piJBGj0eCCb4J5cvaUk13LrxKH3wiZdv5NdKZJpVGXbvVUcM7RUeb -lrbafselPTHnn+7DphsQMbL3RRl3IdCAmaDkmZt+ZQNnzqOJgZyTApd/gKVkrlID -BBPU2rX1MzE++Rq7+sxriVnjJz5wVaWgMv2+HV17y0DYvSlS11fmiBKIFxAbEx4S -HQi9xeWy282qTF0CoVZsFdGXmmANnzk4ISMWAkbBg51qH4938BYQQ0GgZpyhpWPq -cHragWQFf2CNDdfh3/LFrj0ArviB8IZXsq1NO5ClEpxpXMkBLPuiY4YGckLPLySz -yQARAQAB/gcDArQF1AbbNrVT7mST2g0dhVILchpGCDZF3JwW7MveTlwu6m6ATfLi -n/dJuPZVeaghXaAf9+hQwk/9HvofNSX4E6kIQ+3ylciCZRcGj+LgMY/O3RL4ovC5 -TQAWEndntXTcXGxWIxb4dfXw4r+RigzJ34JRBKjV/KG56/9XvsS5hGTkbTfy0WOr -XLaV1/ILiBqwl+G1JAt3Je9+xyRmOhlpj7ivPg3v+XoVMsm0GnLx4K7WyeRsjRNn -oifytw67ZZmjnbCw6inK6EDlyT5Z6SlOfyr2/JaKI4soADLlR/9noEnNAsPs2m0h -4f+qHvQnkgCWPOpo7jQHcmSfuavmV4rrjymYB7vzy+tuG8/FEStmvaBYtm8xN0u0 -LrKa/deB45ruffZKKdlPnCxBwzTCEKVekv3//ZE/guAHB5CsnCgpUx4CeyB9nU3O -rLGa4tmBq8j4+krvOyw68JJMeotNkCK3bPgqsgQ5f0exUXrEaHFxrVx5MnHavmkE -/+zffFRYgdAX8RvmsdIuKrg5kLupZQxaBJZ/Uwt2Gd2QIYqe6slfZS9otUc74w16 -IjiunhLXJhzGbG0Q0N32gw2L1OQwr7oqUKFiCXUZ1P+e5bWKXNLk+bH2p8oGveLJ -VFxmrqhyS0hWo5LW97mMHIXx8gdEtywCJcpwxqy+4tj07KRqE5rNi7Y88SHKoghI -TkI6Ls90ZL4HW735UzZU63ztVnUmBlRBXP439e8jp2QEISYlAaOM45tHZficIscm -y/RYf5Pjc91mi03kZmCaAzKZZ6Nlpw+jtV5i4dQSt79JNC0GgweQrjwISsXpG244 -Z3TB7WM1nBnjO1fDFcgWayfd2vMtf96Nu0lU62fRVY39SwYdjoXjmG8HPf84a8w5 -u5GjPLaH+1ML0z2kpHgMi3gfVCDoPIRuE3Ed0FTkZy6J9Eq97JCP1qrhijVbHd05 -osygfgfQKMcrRjYL6FvG1ltUH2zayyteEasNLaswhNLmTN89VSc3i1YNV8KfdMFs -RDnhDgNZsx7j2UbAXdYuKCK8+3uhnRKkJ3pMjRVJv9nfAbbsa35LCTA8PEmwrooa -GT/QFRv2IFSXVerGqxl9FYo+rUqnDxjD2evHIeFuRgtZiGi0LIqEtuuAMW+r8dF3 -1V/Duj5kMq7Dc54J3kZU9jQXwXAjhBNmfRYj4GxhDTo5/9apNWa8+bwf6dmKuTNP -OTdlPArTA9eZ3pMpmG9pf697m6zu966wCQPqO3IaiDqdHFUV7BKyQvdnd/uqBQjH -CL+XvMQLN8as9Tqb123TDCsyLG3chAvSFPZaPA2Bdx2pUPyVFrjZKpAloH+x2P5N -rF17qdnOr9g4CCt6vCdbnt5n62usL9x5LEbX7wGyIkhSNTAOS/cOqR4/f3thlOxY -nWzUB28gaZWiJmNlejFzsjLLG5zrASVwRqgC1NO5d+BVoXpZdtVBQ1blq1rBDyZS -xkAVLNwaUXmZNMhsMAFKQEl4n7tIpwglDDHAl7PrLe5lPYpqEeScfxPa9UcHpbxo -8ei/vkYehO02PPW7izVKAIURMD2+lEDhO8soxrGfzfUwo/KaEQ35exHnUhf+31WM -WcYAi1viF39J2ybSgYG7ESa9yeno8SQxOD4vFoaw84tBeHkI6oU2AqFAs8ZUbwNZ -NQIdvvmeUEFOTYa1cOswxI/F3Qhf5PYgALTLtrnfm4CIG4JZSU589YzEJANtQeR5 -Z2q3RvzZybpDYQl9GZvmfC4n/g2Rx6ftwytrLmJTtpn/Lte//CaSGfN6TzDyBIiJ -AjYEGAEIACACGwwWIQSMGz+I7Gdekdl+kZr1A641lF0XHAUCXIfjsAAKCRD1A641 -lF0XHF6QEACsEic7jL51OphLpesA0NXsD6VOtHImB/tdBxsaiKLLca3sa1vSgdub -B5oJQFgGqyHam6nnYkKDgyu0g9L4IdUrFZk1bXyGG9Tf2OGFZBQcFg+08tvoOllN -k6JXz6akLIDYU0Y0Kn83wrCcdZ0R2ok41xsIoCeUIX83dgB9/V5ljNatDSEHPIkM -t/JgSx6Su6V5LNdlJQNGJDEF55ZxZNSSNjMMPuMvA7DKnWvRBha4GX4EL6oWQEFG -weJaHe4EkvmgVEnkQwk4e1QX3gigIWPIYzbzMNexmoIIpYiTh34YOggMiYtn/QgK -BKnfHvhKhH3go0CWEH7KdhRMIyTz+QZmBsTtDOuULiv0mm5Lranry+9Kcu7iyFlb -+803b5dEZaRMYaAHm3UF0FEw+OydL2i+jdwGJNyD4T9/s4gJwyW2ky46eq/jfgZf -+jVgRLe6Gzd2hvSBXRMXsmusnog+bWbLHmyPHFKPyK5k7MxXgAvKKRxxvRRbBurY -e6ZlbYNZtEVFMlIgaGzYgKrnDuQQWNn9av0KK3+/NlrYOhiWahpsOdLNcfgAHBuG -LRvufFuJhnX/zbKylORlPh4ZoM7sq58PA+lY6BsLtpO23hQFpQLijUuadMe3Wcnw -l//GtFBBpuCrkBJSs+i63NmOXumTU/t4cso3e+nVFCVr+Q/7+06LHQ== -=brmk +AQgAMhYhBH5bJZXhaTpJAsnyRE933+jeL7rVBQJhXu+yAhsjAgsJBRUICQoCAhYC +Ah4FAheAAAoJEE933+jeL7rVFPwQAJEpU8tx2hZVyU6/AR7iIYMISH/rbtlpqFAx +ujkU/U6/QR0jPWpefWFppY/MErhpRLpojkKyhjJrA24zE7E145H2Wiv5xAwJtwO5 +PbyqdsL+c+YdRw7AkIkqyOkfeJLgEr+gSUv9kplAajnnjpLs1D6+4vUVenQHpHwN +PfZNqA2hHFgktFXicxTouIl/pu094Gs0Y7iJRCz2/RcWdjmvQXtAV+Y/Jso8j+/0 +kIqG47EJOvy9q8eDyFeN+/4Yc+OmjtrcD3trBL+bPNeJT1Xyt9JbAs9deEW44/8s +4QU8IvpC21rVHxZKrdm04e1TgM6wVeFbe6acrNG8d+ccytfSuOW06ikVKA3nPpB3 +HG7sPTfj07MhCnYSgu+i2ul/jZmD++RhbrTQS/G5ARtQT145NUyIl8EnhiLyAHSr +0EGaCe8LHa1fbiXYV3cmLh/5uuYH98XCXlmwR2rhakNQ/u40834vtyyV7JVCJsQV +HPEfqjtmSlOc0rp3DnPCblCyvmEn6vPGRZWFhFaIk9gmV5j9469K3rrQNrk9BNhY +BkMkH3wOJyk3l0rb3M6t0orVUiE8Nia/EmWkfag4+RwRMkrZzg2OPSc5a4X7+8a2 +Sb8UEcxb50mDhHSGiI9p1EY5Bgd/HQ5k/oPfJnqKi0ddIu67IXNX6WyUlQvwl7G7 +32s093fBnQdGBGFe77IBEADRJZoL4MHpU0eobQy/mcLJXs/bQEAzRWWciqG6H31F +uCzaLydN3w87xC2V1jgwug83YRU9O9jlPFta0BdfVzabjvWV7mhMDT8fdfOeaR/L +GmlbwaPgkyQE+YB4guDUDznod6CnufnwINJYR+6V86++Ez7zf5NazZDtshMbmcdx +Z1y1tr2Wh4GdJtzagDnk8ygPpFs308B6Qdaud/6d/IKGnTMSd0eSCIenepnUgsvd +uFwwDNITYlPqT5Ra6or8uCfyNzTxuI//RF4xzCyQ6cCDJLhn2vtuq8J3KODQaDXS +axC/VSg93OyKP+f/xWxXaa9UADn97JsXH2jDDGR0SE5xh2AN2gRxOB7z1Y4L/056 +UZjPMu0u4ZTdkzncqk2gCfSiI/ozdikIIl4abqHEK9h6AlxitbZuP0k6d4lsZzU1 +wakF9PUfYbbH8/KuTQK1UQtJ9j8PF/WZRQQowL8csppu2DwYnk2Bby3N3iCOCX2e +Z5ERk0FUGiEFELQocY6PlRpOsR9iHdqJp4gXuWM4L2cenC4mUYwV98B+6rzW1QhF +jbJID0MOxd2gnvz8ysyHf0KkzHLm7NYesgItVUYLlo5dqMwpn1yEYOk3xUKbN657 +y7w5vLQLPkLIZAZnLepChmEr9PczZRQaY6FXdLL/wWbUgQXUT6d956Akud65Hv7F +gQARAQAB/gcDAgeOhVpXEoQe81Dx3tBEaKLp+IgqQRCaoFfdj1mr1MS09xDKG+xX +mIgdDm6vcc4+qi8tuHtQRHahCtnNCuf3IVMRWMPiNXwY4pCrcbPWOR4R2S3khOeO +XwMBi3ALpjQxHrkkCnUnTMyusvwcNPunOix3LAjAVPwrBm2W1CS4Kxvh8u4aOxqF +oyKqOdsdpx8ofIhbekyykMYwjhCttU4B9V5yyZDZrcuXd0HliKBeuyVN2cDFyNQH +tT1WXpw5ffS3zgfBx1wicSzq0txWvcDF6leuWkFl/BQ2GCa+VpAKHaXEfjnXHSd6 +IntBzg8h6o6AjLOr/evSLPrr2kwWjLFcgOqcNyZX7gHKG9u17fF1Udh60PZGr10q +pc7TC/asE97QSqiZPNQxb09LTVGWBNQ325mDq9XyJ+7toRw39/PkfES8pJPe2adj ++MBYwQK73WkV7Ax6f/t4hQTionZ3xEg3Gh9IEOJxIRfEyqPoGxBQRNN4GvFdxx5B +bbMFmBStOn60m5aQ3qkLyNC+CvR/OmaCaiIRpuawLwtm7tdlSkQu9uTGbadbveLQ +oSZ2GQ+stV0q6ufqRjPPjkWE2AqBthKAxdGjEenf8TaOxo4KBSVydVLenPUJ0uPo +2GczfGR+uBxFmPrTjsRJjCweAV7vzvCjxTN3oEEsPqfUGP606IOYmqtFnATFKJwC +ic2YHtK3lKeiXl3NhLuvezaZBN3WjEZBI536Px+0DLQ53fqz0JuuuSpZcIApjoxe +l2r8A88KM0D6EDHTv4c9OsEfLoOkji5cTactf9CBMH7rw32RSPY0BH867kAE61/6 +8C3oMsqbrAUimBFpeakD/HE+v+humei3NCtextLGogiqrn7NROfxmsvmmFYbQPpZ +LvEhqEr0LjPaRPF4Zhk6BGZe0rO/lryFwZlV6HmQTVg4GpudjKPaqTUidJe4pgY3 +BPz7N9kIkKTSNqY9UmvjiCCyyJDW6mEks1JfmfFLjQerYkXI9mDCUb2wMXRUuIPs +Z8lfRfs8Hhoh3DSTtHanH3/xbid0/QgSc3DV7ddHtFGK2NArFg2Mz6IKif08zG9t +jeC6Cr+fUXK0MRKwTfLgpyIuhicw9NKAKYaGPFRLxp27MZDGvUf8ZjoHVC3SmZaF +kBG08V/cGSdoy/Lz2MmQ8/+CB3KcIkl7uP7bzkbzrfNyRmgvd6ezGvx7g308C8XA +cANgddobjOQow4PVT9SxwSGJI5GdVPKBbc9T9w6GVywEFmKE7C8jVIfsSOYdz1Lj +uLeAtNBA9FeONj/0zBLaewgtJZ4VD2N2gitKS3e17FUYPlwgycidi0Y3TE3IfpcT +DEfuBA7HuJuVm+FHAJWvWAp+12kpkLj3kTk/IG/x2Q4VBBYSivZGGkvlevDB12pA +LwdzEbVhS4CpejDyb2BQ1JKq5JPh1hC4Qs8wUzUUPhi5vh60ZBc2kkammilrc+La +MS0VBfr27jiawMFcU7YoNpL8j2wHA7GOj9IZKuigSkuBjYfgbJtkWTtJWAoESHtf +BRY6yfh5G2BG9liHOFE7VO7ILq75o35dMEAnC01RViHreyIL+uodOEpq3zVktXKv +dLyU8x6Snc0m7Q6sSAqPJiDe6hNd/8jcKhF7ehxbhcgV5X8fq8b9a6iLZCtGgtku +WsGAIyoejge8fkQlLqPvEch84/fRPDWAk/4U+8DKwtzLXMwAGzjPa6N/1ixIkXk+ +kbdHP42tKr+OqLsKZ/FucUj9pGs06RI2SfuK1NmJPVCal66tCmBz7m9/g5OHLIeJ +AjYEGAEIACAWIQR+WyWV4Wk6SQLJ8kRPd9/o3i+61QUCYV7vsgIbDAAKCRBPd9/o +3i+61VsgD/4p25lh/zFk2tGCZLyJDkORfrIsOhQt0F8ApjhpUuBIM3WHJMTOaR5Q +WacQh5XmId1ycbfYfgqvdtLGqPZSJxv4TmtlQkg748Np3/t6i/1io0AmFnas/3I/ +EuCDeKEpp3hkYVixbQRz42OxLlbJXgwDE6GUe/QEPbO0FwFhGv1WMw5Gki9Z5wPb +8rVD6czNahZjzlVQbwuaAsylMvohw2SAs14WvBr+BY2reEHqEcdtI9Xq6HUSmCB4 +N74K/AU54XTvGu7MpBLfKg8vYD+skx9njgQXH/Kafn9hgFhG+RX5qOHe2t4hPk/F +cEK+3L9Wm5l7B2v2K4HddFPnv3M0DkjVkUUu/wQDBJcYFiMygikNL8pExCOe4HA8 +sbe75KpO3Z9huFXk3DaOh885d8dYTyZEjwUkRdYRvNFrRQOTXaWC12ghFGzthAl6 +crCX8HWM1Cm+c3jfYztIvTjEcUbQwd+PibzMCFAYueIfWCPynPouDHrBkBZwAn3X +Ye4zSiD/CPxIPdNi7flKyQfsTdohKlYlGWQGHvS/9WOTy+N9ZoRcguh2wjx4V7Wx +AKNhxpsCAHO0nSY5mUy7HZQOi854MeANH4QfvSqnVI3sWgV6rVj87kfYJdiafU1Y +A+YTDcGjVOO/QzK80cTYqAAACBrSK27y2JJyn1PGTy44Q0mjpO8EFg== +=juL3 -----END PGP PRIVATE KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/regenerate_keys thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/regenerate_keys --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/cli_EncryptSign/regenerate_keys 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/cli_EncryptSign/regenerate_keys 2022-04-15 07:49:22.000000000 +0000 @@ -53,7 +53,7 @@ Subkey-Length: {1} Subkey-Usage: encrypt Name-Real: Test Testovich - Preferences: twofish sha256 sha384 sha512 sha1 zlib + Preferences: aes256 aes512 sha256 sha384 sha512 sha1 zlib Name-Email: {2}""" def __init__(self): @@ -71,7 +71,7 @@ Subkey-Length: {1} Subkey-Usage: encrypt Name-Real: Test Testovich - Preferences: twofish sha256 sha384 sha512 sha1 zlib + Preferences: aes256 aes512 sha256 sha384 sha512 sha1 zlib Name-Email: {2} """ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys 2022-04-15 07:49:22.000000000 +0000 @@ -1,4 +1,4 @@ -21 keys found +23 keys found pub 2048/DSA c8a10a7d78273e10 2018-04-03 [SC] 091c44ce9cfbc3ff7ec7a64dc8a10a7d78273e10 @@ -28,10 +28,10 @@ sub 521/ECDH 9853df2f6d297442 2018-04-03 [E] a9297c86dd0de109e1ebae9c9853df2f6d297442 -pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [SC] +pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] 6bc04a5a3ddb35766b9a40d82fb9179118898e8b uid rsa-rsa -sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [E] +sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e pub 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SC] @@ -64,3 +64,9 @@ sub 256/ECDH 7635401f90d3e533 2018-04-03 [E] c263ec4ce2b3772746ed53227635401f90d3e533 +pub 2048/RSA (Encrypt or Sign) bd860a52d1899c0f 2021-12-24 [SC] + 5aa9362aea07de23a726762cbd860a52d1899c0f +uid rsa-rsa-2 +sub 2048/RSA (Encrypt or Sign) 8e08d46a37414996 2021-12-24 [E] + ca3e4420cf3d3b62d9ee7c6e8e08d46a37414996 + diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_no_bp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_no_bp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_no_bp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_no_bp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,72 @@ +23 keys found + +pub 2048/DSA c8a10a7d78273e10 2018-04-03 [SC] + 091c44ce9cfbc3ff7ec7a64dc8a10a7d78273e10 +uid dsa-eg +sub 3072/Elgamal (Encrypt-Only) 02a5715c3537717e 2018-04-03 [E] + 3409f96f0c57242540702dba02a5715c3537717e + +pub 255/EdDSA cc786278981b0728 2018-04-03 [SC] + 21fc68274aae3b5de39a4277cc786278981b0728 +uid ecc-25519 + +pub 256/ECDSA 23674f21b2441527 2018-04-03 [SC] + b54fdebbb673423a5d0aa54423674f21b2441527 +uid ecc-p256 +sub 256/ECDH 37e285e9e9851491 2018-04-03 [E] + 40e608afbc8d62cdcc08904f37e285e9e9851491 + +pub 384/ECDSA 242a3aa5ea85f44a 2018-04-03 [SC] + ab25cba042dd924c3acc3ed3242a3aa5ea85f44a +uid ecc-p384 +sub 384/ECDH e210e3d554a4fad9 2018-04-03 [E] + cbc2ac55dcd8e4e34fb2f816e210e3d554a4fad9 + +pub 521/ECDSA 2092ca8324263b6a 2018-04-03 [SC] + 4fb39ff6fa4857a4bd7ef5b42092ca8324263b6a +uid ecc-p521 +sub 521/ECDH 9853df2f6d297442 2018-04-03 [E] + a9297c86dd0de109e1ebae9c9853df2f6d297442 + +pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] + 6bc04a5a3ddb35766b9a40d82fb9179118898e8b +uid rsa-rsa +sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] + 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e + +pub 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SCA] + 0633c5f72a198f51e650e4abd0c8a3daf9e0634a +uid ecc-bp256 +sub 256/ECDH 2edabb94d3055f76 2018-04-03 [E] + 08192b478f740360b74c82cc2edabb94d3055f76 + +pub 384/ECDSA 6cf2dce85599ada2 2018-04-03 [SCA] + 5b8a254c823ced98decd10ed6cf2dce85599ada2 +uid ecc-bp384 +sub 384/ECDH cff1bb6f16d28191 2018-04-03 [E] + 76969ce7033d990931df92b2cff1bb6f16d28191 + +pub 512/ECDSA aa5c58d14f7b8f48 2018-04-03 [SCA] + 4c59ab9272aa6a1f60b85bd0aa5c58d14f7b8f48 +uid ecc-bp512 +sub 512/ECDH 20cdaa1482ba79ce 2018-04-03 [E] + 270a7cd0dc6c2e01dce8603620cdaa1482ba79ce + +pub 255/EdDSA 941822a0fc1b30a5 2018-10-15 [SC] + 4c9738a6f2be4e1a796c9b7b941822a0fc1b30a5 +uid eddsa-x25519 +sub 255/ECDH c711187e594376af 2018-10-15 [E] + cfdb2a1f8325cc949ce0b597c711187e594376af + +pub 256/ECDSA 3ea5bb6f9692c1a0 2018-04-03 [SC] + 81f772b57d4ebfe7000a66233ea5bb6f9692c1a0 +uid ecc-p256k1 +sub 256/ECDH 7635401f90d3e533 2018-04-03 [E] + c263ec4ce2b3772746ed53227635401f90d3e533 + +pub 2048/RSA (Encrypt or Sign) bd860a52d1899c0f 2021-12-24 [SC] + 5aa9362aea07de23a726762cbd860a52d1899c0f +uid rsa-rsa-2 +sub 2048/RSA (Encrypt or Sign) 8e08d46a37414996 2021-12-24 [E] + ca3e4420cf3d3b62d9ee7c6e8e08d46a37414996 + diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec 2022-04-15 07:49:22.000000000 +0000 @@ -28,10 +28,10 @@ ssb 521/ECDH 9853df2f6d297442 2018-04-03 [E] a9297c86dd0de109e1ebae9c9853df2f6d297442 -sec 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [SC] +sec 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] 6bc04a5a3ddb35766b9a40d82fb9179118898e8b uid rsa-rsa -ssb 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [E] +ssb 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e sec 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SC] diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec_no_bp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec_no_bp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec_no_bp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec_no_bp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,66 @@ +21 keys found + +sec 2048/DSA c8a10a7d78273e10 2018-04-03 [SC] + 091c44ce9cfbc3ff7ec7a64dc8a10a7d78273e10 +uid dsa-eg +ssb 3072/Elgamal (Encrypt-Only) 02a5715c3537717e 2018-04-03 [E] + 3409f96f0c57242540702dba02a5715c3537717e + +sec 255/EdDSA cc786278981b0728 2018-04-03 [SC] + 21fc68274aae3b5de39a4277cc786278981b0728 +uid ecc-25519 + +sec 256/ECDSA 23674f21b2441527 2018-04-03 [SC] + b54fdebbb673423a5d0aa54423674f21b2441527 +uid ecc-p256 +ssb 256/ECDH 37e285e9e9851491 2018-04-03 [E] + 40e608afbc8d62cdcc08904f37e285e9e9851491 + +sec 384/ECDSA 242a3aa5ea85f44a 2018-04-03 [SC] + ab25cba042dd924c3acc3ed3242a3aa5ea85f44a +uid ecc-p384 +ssb 384/ECDH e210e3d554a4fad9 2018-04-03 [E] + cbc2ac55dcd8e4e34fb2f816e210e3d554a4fad9 + +sec 521/ECDSA 2092ca8324263b6a 2018-04-03 [SC] + 4fb39ff6fa4857a4bd7ef5b42092ca8324263b6a +uid ecc-p521 +ssb 521/ECDH 9853df2f6d297442 2018-04-03 [E] + a9297c86dd0de109e1ebae9c9853df2f6d297442 + +sec 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] + 6bc04a5a3ddb35766b9a40d82fb9179118898e8b +uid rsa-rsa +ssb 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] + 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e + +sec 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SCA] + 0633c5f72a198f51e650e4abd0c8a3daf9e0634a +uid ecc-bp256 +ssb 256/ECDH 2edabb94d3055f76 2018-04-03 [E] + 08192b478f740360b74c82cc2edabb94d3055f76 + +sec 384/ECDSA 6cf2dce85599ada2 2018-04-03 [SCA] + 5b8a254c823ced98decd10ed6cf2dce85599ada2 +uid ecc-bp384 +ssb 384/ECDH cff1bb6f16d28191 2018-04-03 [E] + 76969ce7033d990931df92b2cff1bb6f16d28191 + +sec 512/ECDSA aa5c58d14f7b8f48 2018-04-03 [SCA] + 4c59ab9272aa6a1f60b85bd0aa5c58d14f7b8f48 +uid ecc-bp512 +ssb 512/ECDH 20cdaa1482ba79ce 2018-04-03 [E] + 270a7cd0dc6c2e01dce8603620cdaa1482ba79ce + +sec 255/EdDSA 941822a0fc1b30a5 2018-10-15 [SC] + 4c9738a6f2be4e1a796c9b7b941822a0fc1b30a5 +uid eddsa-x25519 +ssb 255/ECDH c711187e594376af 2018-10-15 [E] + cfdb2a1f8325cc949ce0b597c711187e594376af + +sec 256/ECDSA 3ea5bb6f9692c1a0 2018-04-03 [SC] + 81f772b57d4ebfe7000a66233ea5bb6f9692c1a0 +uid ecc-p256k1 +ssb 256/ECDH 7635401f90d3e533 2018-04-03 [E] + c263ec4ce2b3772746ed53227635401f90d3e533 + diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys 2022-04-15 07:49:22.000000000 +0000 @@ -1,4 +1,4 @@ -21 keys found +23 keys found pub 2048/DSA c8a10a7d78273e10 2018-04-03 [SC] 091c44ce9cfbc3ff7ec7a64dc8a10a7d78273e10 @@ -28,10 +28,10 @@ sub 521/ECDH 9853df2f6d297442 2018-04-03 [E] a9297c86dd0de109e1ebae9c9853df2f6d297442 -pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [SC] +pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] 6bc04a5a3ddb35766b9a40d82fb9179118898e8b uid rsa-rsa -sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [E] +sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e pub 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SC] @@ -64,3 +64,9 @@ sub 256/ECDH 7635401f90d3e533 2018-04-03 [E] c263ec4ce2b3772746ed53227635401f90d3e533 +pub 2048/RSA (Encrypt or Sign) bd860a52d1899c0f 2021-12-24 [SC] + 5aa9362aea07de23a726762cbd860a52d1899c0f +uid rsa-rsa-2 +sub 2048/RSA (Encrypt or Sign) 8e08d46a37414996 2021-12-24 [E] + ca3e4420cf3d3b62d9ee7c6e8e08d46a37414996 + diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys_no_bp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys_no_bp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys_no_bp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys_no_bp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,72 @@ +23 keys found + +pub 2048/DSA c8a10a7d78273e10 2018-04-03 [SC] + 091c44ce9cfbc3ff7ec7a64dc8a10a7d78273e10 +uid dsa-eg +sub 3072/Elgamal (Encrypt-Only) 02a5715c3537717e 2018-04-03 [E] + 3409f96f0c57242540702dba02a5715c3537717e + +pub 255/EdDSA cc786278981b0728 2018-04-03 [SC] + 21fc68274aae3b5de39a4277cc786278981b0728 +uid ecc-25519 + +pub 256/ECDSA 23674f21b2441527 2018-04-03 [SC] + b54fdebbb673423a5d0aa54423674f21b2441527 +uid ecc-p256 +sub 256/ECDH 37e285e9e9851491 2018-04-03 [E] + 40e608afbc8d62cdcc08904f37e285e9e9851491 + +pub 384/ECDSA 242a3aa5ea85f44a 2018-04-03 [SC] + ab25cba042dd924c3acc3ed3242a3aa5ea85f44a +uid ecc-p384 +sub 384/ECDH e210e3d554a4fad9 2018-04-03 [E] + cbc2ac55dcd8e4e34fb2f816e210e3d554a4fad9 + +pub 521/ECDSA 2092ca8324263b6a 2018-04-03 [SC] + 4fb39ff6fa4857a4bd7ef5b42092ca8324263b6a +uid ecc-p521 +sub 521/ECDH 9853df2f6d297442 2018-04-03 [E] + a9297c86dd0de109e1ebae9c9853df2f6d297442 + +pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] + 6bc04a5a3ddb35766b9a40d82fb9179118898e8b +uid rsa-rsa +sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] + 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e + +pub 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SCA] + 0633c5f72a198f51e650e4abd0c8a3daf9e0634a +uid ecc-bp256 +sub 256/ECDH 2edabb94d3055f76 2018-04-03 [E] + 08192b478f740360b74c82cc2edabb94d3055f76 + +pub 384/ECDSA 6cf2dce85599ada2 2018-04-03 [SCA] + 5b8a254c823ced98decd10ed6cf2dce85599ada2 +uid ecc-bp384 +sub 384/ECDH cff1bb6f16d28191 2018-04-03 [E] + 76969ce7033d990931df92b2cff1bb6f16d28191 + +pub 512/ECDSA aa5c58d14f7b8f48 2018-04-03 [SCA] + 4c59ab9272aa6a1f60b85bd0aa5c58d14f7b8f48 +uid ecc-bp512 +sub 512/ECDH 20cdaa1482ba79ce 2018-04-03 [E] + 270a7cd0dc6c2e01dce8603620cdaa1482ba79ce + +pub 255/EdDSA 941822a0fc1b30a5 2018-10-15 [SC] + 4c9738a6f2be4e1a796c9b7b941822a0fc1b30a5 +uid eddsa-x25519 +sub 255/ECDH c711187e594376af 2018-10-15 [E] + cfdb2a1f8325cc949ce0b597c711187e594376af + +pub 256/ECDSA 3ea5bb6f9692c1a0 2018-04-03 [SC] + 81f772b57d4ebfe7000a66233ea5bb6f9692c1a0 +uid ecc-p256k1 +sub 256/ECDH 7635401f90d3e533 2018-04-03 [E] + c263ec4ce2b3772746ed53227635401f90d3e533 + +pub 2048/RSA (Encrypt or Sign) bd860a52d1899c0f 2021-12-24 [SC] + 5aa9362aea07de23a726762cbd860a52d1899c0f +uid rsa-rsa-2 +sub 2048/RSA (Encrypt or Sign) 8e08d46a37414996 2021-12-24 [E] + ca3e4420cf3d3b62d9ee7c6e8e08d46a37414996 + diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs 2022-04-15 07:49:22.000000000 +0000 @@ -1,4 +1,4 @@ -21 keys found +23 keys found pub 2048/DSA c8a10a7d78273e10 2018-04-03 [SC] 091c44ce9cfbc3ff7ec7a64dc8a10a7d78273e10 @@ -33,11 +33,11 @@ sub 521/ECDH 9853df2f6d297442 2018-04-03 [E] a9297c86dd0de109e1ebae9c9853df2f6d297442 -pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [SC] +pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] 6bc04a5a3ddb35766b9a40d82fb9179118898e8b uid rsa-rsa -sig 2fb9179118898e8b 2019-02-02 rsa-rsa -sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [E] +sig 2fb9179118898e8b 2019-02-02 [unknown] +sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e pub 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SC] @@ -75,3 +75,10 @@ sub 256/ECDH 7635401f90d3e533 2018-04-03 [E] c263ec4ce2b3772746ed53227635401f90d3e533 +pub 2048/RSA (Encrypt or Sign) bd860a52d1899c0f 2021-12-24 [SC] + 5aa9362aea07de23a726762cbd860a52d1899c0f +uid rsa-rsa-2 +sig bd860a52d1899c0f 2021-12-24 rsa-rsa-2 +sub 2048/RSA (Encrypt or Sign) 8e08d46a37414996 2021-12-24 [E] + ca3e4420cf3d3b62d9ee7c6e8e08d46a37414996 + diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs_no_bp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs_no_bp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs_no_bp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs_no_bp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,84 @@ +23 keys found + +pub 2048/DSA c8a10a7d78273e10 2018-04-03 [SC] + 091c44ce9cfbc3ff7ec7a64dc8a10a7d78273e10 +uid dsa-eg +sig c8a10a7d78273e10 2019-02-02 dsa-eg +sub 3072/Elgamal (Encrypt-Only) 02a5715c3537717e 2018-04-03 [E] + 3409f96f0c57242540702dba02a5715c3537717e + +pub 255/EdDSA cc786278981b0728 2018-04-03 [SC] + 21fc68274aae3b5de39a4277cc786278981b0728 +uid ecc-25519 +sig cc786278981b0728 2019-02-02 ecc-25519 + +pub 256/ECDSA 23674f21b2441527 2018-04-03 [SC] + b54fdebbb673423a5d0aa54423674f21b2441527 +uid ecc-p256 +sig 23674f21b2441527 2019-02-02 ecc-p256 +sub 256/ECDH 37e285e9e9851491 2018-04-03 [E] + 40e608afbc8d62cdcc08904f37e285e9e9851491 + +pub 384/ECDSA 242a3aa5ea85f44a 2018-04-03 [SC] + ab25cba042dd924c3acc3ed3242a3aa5ea85f44a +uid ecc-p384 +sig 242a3aa5ea85f44a 2019-02-02 ecc-p384 +sub 384/ECDH e210e3d554a4fad9 2018-04-03 [E] + cbc2ac55dcd8e4e34fb2f816e210e3d554a4fad9 + +pub 521/ECDSA 2092ca8324263b6a 2018-04-03 [SC] + 4fb39ff6fa4857a4bd7ef5b42092ca8324263b6a +uid ecc-p521 +sig 2092ca8324263b6a 2019-02-02 ecc-p521 +sub 521/ECDH 9853df2f6d297442 2018-04-03 [E] + a9297c86dd0de109e1ebae9c9853df2f6d297442 + +pub 3072/RSA (Encrypt or Sign) 2fb9179118898e8b 2018-04-03 [ESCA] + 6bc04a5a3ddb35766b9a40d82fb9179118898e8b +uid rsa-rsa +sig 2fb9179118898e8b 2019-02-02 [unknown] +sub 3072/RSA (Encrypt or Sign) 6e2f73008f8b8d6e 2018-04-03 [ESCA] + 20fe5b1ab68c2d7210fb08aa6e2f73008f8b8d6e + +pub 256/ECDSA d0c8a3daf9e0634a 2018-04-03 [SCA] + 0633c5f72a198f51e650e4abd0c8a3daf9e0634a +uid ecc-bp256 +sig d0c8a3daf9e0634a 2019-02-02 [unknown] +sub 256/ECDH 2edabb94d3055f76 2018-04-03 [E] + 08192b478f740360b74c82cc2edabb94d3055f76 + +pub 384/ECDSA 6cf2dce85599ada2 2018-04-03 [SCA] + 5b8a254c823ced98decd10ed6cf2dce85599ada2 +uid ecc-bp384 +sig 6cf2dce85599ada2 2019-02-02 [unknown] +sub 384/ECDH cff1bb6f16d28191 2018-04-03 [E] + 76969ce7033d990931df92b2cff1bb6f16d28191 + +pub 512/ECDSA aa5c58d14f7b8f48 2018-04-03 [SCA] + 4c59ab9272aa6a1f60b85bd0aa5c58d14f7b8f48 +uid ecc-bp512 +sig aa5c58d14f7b8f48 2019-02-02 [unknown] +sub 512/ECDH 20cdaa1482ba79ce 2018-04-03 [E] + 270a7cd0dc6c2e01dce8603620cdaa1482ba79ce + +pub 255/EdDSA 941822a0fc1b30a5 2018-10-15 [SC] + 4c9738a6f2be4e1a796c9b7b941822a0fc1b30a5 +uid eddsa-x25519 +sig 941822a0fc1b30a5 2018-10-15 eddsa-x25519 +sub 255/ECDH c711187e594376af 2018-10-15 [E] + cfdb2a1f8325cc949ce0b597c711187e594376af + +pub 256/ECDSA 3ea5bb6f9692c1a0 2018-04-03 [SC] + 81f772b57d4ebfe7000a66233ea5bb6f9692c1a0 +uid ecc-p256k1 +sig 3ea5bb6f9692c1a0 2019-02-02 ecc-p256k1 +sub 256/ECDH 7635401f90d3e533 2018-04-03 [E] + c263ec4ce2b3772746ed53227635401f90d3e533 + +pub 2048/RSA (Encrypt or Sign) bd860a52d1899c0f 2021-12-24 [SC] + 5aa9362aea07de23a726762cbd860a52d1899c0f +uid rsa-rsa-2 +sig bd860a52d1899c0f 2021-12-24 rsa-rsa-2 +sub 2048/RSA (Encrypt or Sign) 8e08d46a37414996 2021-12-24 [E] + ca3e4420cf3d3b62d9ee7c6e8e08d46a37414996 + Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_fuzz_dump/timeout-7e498daecad7ee646371a466d4a317c59fe7db89 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_fuzz_dump/timeout-7e498daecad7ee646371a466d4a317c59fe7db89 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_fuzz_keyimport/leak_371b211d7e9cf9857befcf06c7da74835e249ee7 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_fuzz_keyimport/leak_371b211d7e9cf9857befcf06c7da74835e249ee7 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_fuzz_keyring_kbx/leak-b02cd1c6b70c10a8a673a34ba3770b39468b7ddf and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_fuzz_keyring_kbx/leak-b02cd1c6b70c10a8a673a34ba3770b39468b7ddf differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_fuzz_sigimport/timeout-821848a7b6b667fc41e5ff130415b3efd22ed118 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_fuzz_sigimport/timeout-821848a7b6b667fc41e5ff130415b3efd22ed118 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_fuzz_verify/timeout-25b8c9d824c8eb492c827689795748298a2b0a46 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_fuzz_verify/timeout-25b8c9d824c8eb492c827689795748298a2b0a46 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_fuzz_verify/timeout-c2aff538c73b447bca689005e9762840b5a022d0 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_fuzz_verify/timeout-c2aff538c73b447bca689005e9762840b5a022d0 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_fuzz_verify_detached/outofmemory-dea88a4aa4ab5fec1291446db702ee893d5559cf and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_fuzz_verify_detached/outofmemory-dea88a4aa4ab5fec1291446db702ee893d5559cf differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/alice-sub-sig-fp.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/alice-sub-sig-fp.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/alice-sub-sig-keyid.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/alice-sub-sig-keyid.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/alice-wrong-mpi-bit-count.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/alice-wrong-mpi-bit-count.pgp differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,11 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xjMEYUh6kxYJKwYBBAHaRw8BAQdAko/IzElBsrhU/2QuryqTfQIzWq/EeTwfe3Wjf7h8Go/NF2Vk +ZHNhLTI1NTE5LW5vbi10d2Vha2VkwosEExYIADMWIQTd4O5TnAF9K9P2BKUxdvwUhqolKAUCYUh6 +kwIbAwULCQgHAgYVCAkKCwIFFgIDAQAACgkQMXb8FIaqJSjmYwEA7tHi9kUlqbflFgWdg99+nmsr +9SmsoVGF4uqndkTo7KUA/3UsufMfj/c2VQ1mvr1skenQMmoaKBi0LJoGyBTEbQsKzjgEYUh6kxIK +KwYBBAGXVQEFAQEHQGpxh4g26kNnIyevXMYqK+rR4GzBBKZ0CrN2L9KSm/h7AwEIB8J4BBgWCAAg +FiEE3eDuU5wBfSvT9gSlMXb8FIaqJSgFAmFIepMCGwwACgkQMXb8FIaqJSgM9QEAjMKUoK6RER1Y +a0DG8fUmNSpgVVrMU1zx8agUxpatEZsA/30HthI0z9dDeOuqZhF92n5q7r08AZZW1PjMj0JXrtYP +=wnec +-----END PGP PUBLIC KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,13 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +xVgEYUh6kxYJKwYBBAHaRw8BAQdAko/IzElBsrhU/2QuryqTfQIzWq/EeTwfe3Wjf7h8Go8AAP9V +pLY7sMkGlT9OporbTWHC4bxavj60oTVDLuB2CSINKA+pzRdlZGRzYS0yNTUxOS1ub24tdHdlYWtl +ZMKLBBMWCAAzFiEE3eDuU5wBfSvT9gSlMXb8FIaqJSgFAmFIepMCGwMFCwkIBwIGFQgJCgsCBRYC +AwEAAAoJEDF2/BSGqiUo5mMBAO7R4vZFJam35RYFnYPffp5rK/UprKFRheLqp3ZE6OylAP91LLnz +H4/3NlUNZr69bJHp0DJqGigYtCyaBsgUxG0LCsddBGFIepMSCisGAQQBl1UBBQEBB0BqcYeINupD +ZyMnr1zGKivq0eBswQSmdAqzdi/Skpv4ewMBCAcAAQCXobu+cYjidL6kUffBZu+jzS/GrF3sWw1k +OrvZ5Jr6rBPZwngEGBYIACAWIQTd4O5TnAF9K9P2BKUxdvwUhqolKAUCYUh6kwIbDAAKCRAxdvwU +hqolKAz1AQCMwpSgrpERHVhrQMbx9SY1KmBVWsxTXPHxqBTGlq0RmwD/fQe2EjTP10N466pmEX3a +fmruvTwBllbU+MyPQleu1g8= +=o9U3 +-----END PGP PRIVATE KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec-prot.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec-prot.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec-prot.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-non-tweaked-sec-prot.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,14 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +xYYEYUh6kxYJKwYBBAHaRw8BAQdAko/IzElBsrhU/2QuryqTfQIzWq/EeTwfe3Wjf7h8Go/+CQMI +HjyNcbEWswD9/h842EF8C4xGQz84EQzsW0YHOa1NkDqzVbY0WKctc2oxaHAM+7gN6yoIH9jl9oJH +1Ceec1sUdExyrwh5fxdjucSFz6jkX80XZWRkc2EtMjU1MTktbm9uLXR3ZWFrZWTCiwQTFggAMxYh +BN3g7lOcAX0r0/YEpTF2/BSGqiUoBQJhSHqTAhsDBQsJCAcCBhUICQoLAgUWAgMBAAAKCRAxdvwU +hqolKOZjAQDu0eL2RSWpt+UWBZ2D336eayv1KayhUYXi6qd2ROjspQD/dSy58x+P9zZVDWa+vWyR +6dAyahooGLQsmgbIFMRtCwrHiwRhSHqTEgorBgEEAZdVAQUBAQdAanGHiDbqQ2cjJ69cxior6tHg +bMEEpnQKs3Yv0pKb+HsDAQgH/gkDCDYHyCxU90o5/HC1kV5DtPawPtr38yk4D8r+oVUw7+jIcg2o +PCZbEsb2xBNEHDRc0aUX7htMuVonyg699WGl92WgCU6rgT70EdeKQjKik/bCeAQYFggAIBYhBN3g +7lOcAX0r0/YEpTF2/BSGqiUoBQJhSHqTAhsMAAoJEDF2/BSGqiUoDPUBAIzClKCukREdWGtAxvH1 +JjUqYFVazFNc8fGoFMaWrRGbAP99B7YSNM/XQ3jrqmYRfdp+au69PAGWVtT4zI9CV67WDw== +=Y4FB +-----END PGP PRIVATE KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-sec.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-sec.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-sec.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-sec.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,13 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +xVgEYUh6kxYJKwYBBAHaRw8BAQdAko/IzElBsrhU/2QuryqTfQIzWq/EeTwfe3Wjf7h8Go8AAP9V +pLY7sMkGlT9OporbTWHC4bxavj60oTVDLuB2CSINKA+pzRdlZGRzYS0yNTUxOS1ub24tdHdlYWtl +ZMKLBBMWCAAzFiEE3eDuU5wBfSvT9gSlMXb8FIaqJSgFAmFIepMCGwMFCwkIBwIGFQgJCgsCBRYC +AwEAAAoJEDF2/BSGqiUo5mMBAO7R4vZFJam35RYFnYPffp5rK/UprKFRheLqp3ZE6OylAP91LLnz +H4/3NlUNZr69bJHp0DJqGigYtCyaBsgUxG0LCsddBGFIepMSCisGAQQBl1UBBQEBB0BqcYeINupD +ZyMnr1zGKivq0eBswQSmdAqzdi/Skpv4ewMBCAcAAP9Xobu+cYjidL6kUffBZu+jzS/GrF3sWw1k +OrvZ5Jr6qBSTwngEGBYIACAWIQTd4O5TnAF9K9P2BKUxdvwUhqolKAUCYUh6kwIbDAAKCRAxdvwU +hqolKAz1AQCMwpSgrpERHVhrQMbx9SY1KmBVWsxTXPHxqBTGlq0RmwD/fQe2EjTP10N466pmEX3a +fmruvTwBllbU+MyPQleu1g8= +=uGwR +-----END PGP PRIVATE KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-wrong-crc.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-wrong-crc.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-wrong-crc.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-25519-tweaked-wrong-crc.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,13 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +xVgEYUh6kxYJKwYBBAHaRw8BAQdAko/IzElBsrhU/2QuryqTfQIzWq/EeTwfe3Wjf7h8Go8AAP9V +pLY7sMkGlT9OporbTWHC4bxavj60oTVDLuB2CSINKA+pzRdlZGRzYS0yNTUxOS1ub24tdHdlYWtl +ZMKLBBMWCAAzFiEE3eDuU5wBfSvT9gSlMXb8FIaqJSgFAmFIepMCGwMFCwkIBwIGFQgJCgsCBRYC +AwEAAAoJEDF2/BSGqiUo5mMBAO7R4vZFJam35RYFnYPffp5rK/UprKFRheLqp3ZE6OylAP91LLnz +H4/3NlUNZr69bJHp0DJqGigYtCyaBsgUxG0LCsddBGFIepMSCisGAQQBl1UBBQEBB0BqcYeINupD +ZyMnr1zGKivq0eBswQSmdAqzdi/Skpv4ewMBCAcAAP5Xobu+cYjidL6kUffBZu+jzS/GrF3sWw1k +OrvZ5Jr6qBPZwngEGBYIACAWIQTd4O5TnAF9K9P2BKUxdvwUhqolKAUCYUh6kwIbDAAKCRAxdvwU +hqolKAz1AQCMwpSgrpERHVhrQMbx9SY1KmBVWsxTXPHxqBTGlq0RmwD/fQe2EjTP10N466pmEX3a +fmruvTwBllbU+MyPQleu1g8= +=Ys8t +-----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-critical-notations.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-critical-notations.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-critical-notations-sec.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-critical-notations-sec.pgp differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-pub.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-pub.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-pub.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-pub.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,11 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xjMEYVWOgxYJKwYBBAHaRw8BAQdAzJddic9PzthiDPOayDZvvVFl8Af6uqMkv04Hz8X8wMXNDWVk +ZHNhX3NtYWxsX3jCiwQTFggAMxYhBCT7Uh0s1zK+6oyVgHvFW5vc424YBQJhVY6DAhsDBQsJCAcC +BhUICQoLAgUWAgMBAAAKCRB7xVub3ONuGH/eAQCHhZTc7ySEITCaIDf31aZlQTdNnAuJFDVg9fzO +zvoBkAD/dY5XG4PRpEjLSh1/VW0WGLgAcApD2g97VxTZdvFaWwXOOARhVY6DEgorBgEEAZdVAQUB +AQdAOZW14cWUkEPNLMZzW1sUGoyAqLPKZ336iGxcFEdkJGEDAQgHwngEGBYIACAWIQQk+1IdLNcy +vuqMlYB7xVub3ONuGAUCYVWOgwIbDAAKCRB7xVub3ONuGJ8rAQCyeCuKXRNVyu0J49xALC7nEWRS +5osENDRRxLyein0iOAEAlzK6LHkWgDSE1p6z+5G6CiuUZO8Y0rsirPhQiEGqAQE= +=oEKi +-----END PGP PUBLIC KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-sec.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-sec.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-sec.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eddsa-small-x-sec.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,14 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +xYUEYVWOgxYJKwYBBAHaRw8BAQdAzJddic9PzthiDPOayDZvvVFl8Af6uqMkv04Hz8X8wMX+CQMI +Yncs4llakFX/JaevHHflKYZ8qMxss6QihgBZUoRTfGULv4B9e/vGuSgRHw1lP3KwPYWPxjfq63d9 +gRtQq6JQuYS4KRmLAb/lftwJR3IezQ1lZGRzYV9zbWFsbF94wosEExYIADMWIQQk+1IdLNcyvuqM +lYB7xVub3ONuGAUCYVWOgwIbAwULCQgHAgYVCAkKCwIFFgIDAQAACgkQe8Vbm9zjbhh/3gEAh4WU +3O8khCEwmiA399WmZUE3TZwLiRQ1YPX8zs76AZAA/3WOVxuD0aRIy0odf1VtFhi4AHAKQ9oPe1cU +2XbxWlsFx4sEYVWOgxIKKwYBBAGXVQEFAQEHQDmVteHFlJBDzSzGc1tbFBqMgKizymd9+ohsXBRH +ZCRhAwEIB/4JAwjMjGN1bB1esf/tvNBzXzuctSz1WHPkMxwAYT1xe3hsxc9rncR2SpURFXWsQLeg +7lHW/WvPSVo3bXWIQ27shrpbkhGQ+5E2OaXSmgCByEaawngEGBYIACAWIQQk+1IdLNcyvuqMlYB7 +xVub3ONuGAUCYVWOgwIbDAAKCRB7xVub3ONuGJ8rAQCyeCuKXRNVyu0J49xALC7nEWRS5osENDRR +xLyein0iOAEAlzK6LHkWgDSE1p6z+5G6CiuUZO8Y0rsirPhQiEGqAQE= +=65Pa +-----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eg-small-subgroup-pub.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eg-small-subgroup-pub.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eg-small-subgroup-sec-enc.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eg-small-subgroup-sec-enc.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eg-small-subgroup-sec.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-eg-small-subgroup-sec.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-expired-cert-direct.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-expired-cert-direct.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-primary-uid-conflict-pub.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-primary-uid-conflict-pub.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-primary-uid-conflict-sec.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-primary-uid-conflict-sec.pgp differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-pub.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-pub.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-pub.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-pub.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,26 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsBNBDuaygABCADt/ym+Cc2JVpjUoIkwS+eqWt/pKh73Vl3jRbPEQgOAyY0l2pVlBOovkC74RW3c +5HN9QvZUC94njbW52vQVUOqRDRNDDT4dl4djpAxl5hUP65zgYC3lTISzePs1zjq4Z0H69AfH7qyb +/49cuqHVVQAQC2ez/Zn31A0SrSZBQlCJND2vDK4BmK07pSv4d3nPqmqaSvoCDDzgS1sAvcsSMFwW +EgO3suJP3qale0CEE7xHEgoKAuHsf3j8mfoD7c4U36lfPNbQLlzc9k/bS/gkCOChoq1T6pqyZtWp +oSHiWWiVI8MdgwIyfDXjzX+gPc7jxzKNdNHu1D+K5BEQVjQXU9W7ABEBAAHNDHJzYS1rZXktMjAw +McLAhwQTAQgAMRYhBDtD89a/PyOnIzH9TWyXZJPEYz+1BQI7msoAAhsDBAsJCAcFFQgJCgsFFgID +AQAACgkQbJdkk8RjP7UURwf8D5nyfLOIRHoTgUJjnIVbluJR8FFum3/qt405o/NrLIXXz+F1MAF8 +nQBhkgDOMnWk5Keek2C8VGSR6FIyiai0umDvTx4OccIqVyZGiSwxEIF3Ts05RlF0j1UywmI/CTBT +GSg/Dsk0ujnHwJQmzgQvtbzbyehQ/wCqn48hSBEocU3d6KaVuH7TWm0ZQ8YYxE6SGwDdngBUmqU+ +uWxapoXKltb0g/xsFOmlrYCFKhFkrjsgHco8XBXEgy9E/uFDAPZbC1FVuHnFaJllEqLdUtioXs3P +cUI0OHGwZHXnZuRBbeeJmvYKtGNN7u6qhCwPquPN+95uBGUC9k81npFQHUt5ss7ATQQ7msoAAQgA +5YL/OTcsuQHcTwa1kq2N+NcehTbDvZQy1he7mgJaNPo9bNWAHtqm1Ox5Dq6HjHY6eVYtTbVudeOx +dxrS/BWCbkaaSPX0yGUpM7OsUQKl2/zrgDEmEXYwEtu0bj/fFA3IsETQdy4UEr8Uj4rzizqBj8au +BgU5D1R+Ec6cK1caNmJgSUEJEThxEekJk+NNH8QaXE2Todho7nvcBTr8Tpyue/w2Wdso0Wcrvefz +gWqrwe35iZYOemkLt0OqVOJuG3XHHhO0wZiDKwT7zqGUgPISp0jDZxgLnKMbRuj3gqQcPfL/LkN8 +7dLWlqsKQHBygSaM7FF1qKSd4XmSWV4g4q1NMQARAQABwsB2BBgBCAAgFiEEO0Pz1r8/I6cjMf1N +bJdkk8RjP7UFAjuaygACGwwACgkQbJdkk8RjP7WHhAf/Ur/fsfSSQKft6FeCaPaWznfbgnwl0DXS +b/gUzZAMTAEwfLS/4LxywiJ5qbVhRf5N7CwP0fbyg5VZFYa86t15iWheqOAUFZuZ0NEsYpqyVkGb +W50rxuHU/Hps05rqH43aUIJJyzpxndniBMxBelB8QobXnjmUK97iw0e9uoMiPj+aqSzyW/ecHdwD +LyJyFs3jB1kRSUCcZEUtZVa3ij2NSnY+LOykXiRf+2GymuoPM6lJG5KCLFD+SQEBpFk1TTiaQggW +z3nPu1xqUDOx2MjApLDF7T/rLCSx1u4Wa45Vzx3tTfm8vO0E2YiPFpAHZ+BMXlKgstp97YhCYJN5 +zLgslg== +=Wxb0 +-----END PGP PUBLIC KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-sec.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-sec.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-sec.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-rsa-2001-sec.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,50 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +xcMGBDuaygABCADt/ym+Cc2JVpjUoIkwS+eqWt/pKh73Vl3jRbPEQgOAyY0l2pVlBOovkC74RW3c +5HN9QvZUC94njbW52vQVUOqRDRNDDT4dl4djpAxl5hUP65zgYC3lTISzePs1zjq4Z0H69AfH7qyb +/49cuqHVVQAQC2ez/Zn31A0SrSZBQlCJND2vDK4BmK07pSv4d3nPqmqaSvoCDDzgS1sAvcsSMFwW +EgO3suJP3qale0CEE7xHEgoKAuHsf3j8mfoD7c4U36lfPNbQLlzc9k/bS/gkCOChoq1T6pqyZtWp +oSHiWWiVI8MdgwIyfDXjzX+gPc7jxzKNdNHu1D+K5BEQVjQXU9W7ABEBAAH+CQMIh7sH7vVO1EXo +XdBJRXeI3I62/cAgzfXZf8k43cZXIZl65R22iPoCtefrPHOV6/jqD3EQ/aWMhJViKWz/WW7intjg +TvXjHN2Z107Uj7bP7KUfz9Nm2HoKWA/GjDFRAnknk3ddEPbkdJ9AOlT8nFXeujQoxA4gKIyxJ+DI +A34wkv+kPSbVgKW07YD/mWSQTk50mRyNOl9Y07wHqq3RPSyugJw786Z4HWcr308IS6eVgm4MwwaU +DC5zHf5GsEqRAPiEebJhlg4+aNey2Kchlvd8bZ8G939ljsjPDwNiJPAP9OdnHxXZhrIy5QEjTHZ+ +yZlp689STEnwQ9QoM9hrLzd25oaFYpGuJrg9rG+qj8gPlnXVY/xAJ7YdVdm2Vr3hMuKZ/DLVTtly +PRRpC0nyguOjiSQ3QewqK0nAUOl5RZZPLr+tXJxzMNdfKIRx5aTQhJtBr/ES7Dns4efF6RqVUDeG +WWFrC+IPxgtny2Zn6hG91fm+da8+PUbvND8ZnTunbPTgnE/olZjEJN8hUXLknJG4t6ZWNwL2AROM +GlSFmmQZK4vuJah/mPN9Vv2uAjd8invu6qVF08b7WgR/YN6QpF4KUx1e3ShLAfqqH5I8dgKKi1Aa +ZbsWux3pDaP9nPR1Kg2Wf7WRRB72ahW8bXuK+LQjqGSzaZlHq0k0ZmOqVNG/+aFt3pCap2uzeeXk +ytZcafH8InbjzkJ78J5G83s728/YTRufwR7TasvXdLMt67VFwJcWzLsAWYn0Hmlepcg1vENhkak3 +K/Bq1laU5khGr+Y2/U3zV8vyzkN/WGQyTDuZRAEMD3LAVJpyeVJqTq502uzBrCEwJHIS+ZdzIuVH +qfkYl5QYzCc7iH0eChZdTFSMYRyvB4udZiCjsnmL4ePnkJKXGC37WbBTr9RsD9AAwzaqNoYZw0me +zQxyc2Eta2V5LTIwMDHCwIcEEwEIADEWIQQ7Q/PWvz8jpyMx/U1sl2STxGM/tQUCO5rKAAIbAwQL +CQgHBRUICQoLBRYCAwEAAAoJEGyXZJPEYz+1FEcH/A+Z8nyziER6E4FCY5yFW5biUfBRbpt/6reN +OaPzayyF18/hdTABfJ0AYZIAzjJ1pOSnnpNgvFRkkehSMomotLpg708eDnHCKlcmRoksMRCBd07N +OUZRdI9VMsJiPwkwUxkoPw7JNLo5x8CUJs4EL7W828noUP8Aqp+PIUgRKHFN3eimlbh+01ptGUPG +GMROkhsA3Z4AVJqlPrlsWqaFypbW9IP8bBTppa2AhSoRZK47IB3KPFwVxIMvRP7hQwD2WwtRVbh5 +xWiZZRKi3VLYqF7Nz3FCNDhxsGR152bkQW3niZr2CrRjTe7uqoQsD6rjzfvebgRlAvZPNZ6RUB1L +ebLHwwUEO5rKAAEIAOWC/zk3LLkB3E8GtZKtjfjXHoU2w72UMtYXu5oCWjT6PWzVgB7aptTseQ6u +h4x2OnlWLU21bnXjsXca0vwVgm5Gmkj19MhlKTOzrFECpdv864AxJhF2MBLbtG4/3xQNyLBE0Hcu +FBK/FI+K84s6gY/GrgYFOQ9UfhHOnCtXGjZiYElBCRE4cRHpCZPjTR/EGlxNk6HYaO573AU6/E6c +rnv8NlnbKNFnK73n84Fqq8Ht+YmWDnppC7dDqlTibht1xx4TtMGYgysE+86hlIDyEqdIw2cYC5yj +G0bo94KkHD3y/y5DfO3S1parCkBwcoEmjOxRdaikneF5klleIOKtTTEAEQEAAf4JAwiJF+UcFJgg +beg7H440c2oHCmulWS/eCm+FY7gQLyWnPIYx40Okh4B9RCQfLI6rYMTH00pBJPvw7jbJ61eWk0c3 +lri+ZNctq+lvJE0vDvESzv+D2B8g/hfzSooPVhKK4kIvFJkJpkKubEFxyarXBRvoSbPmoLp1E+3F +kFCALv10VwdHa9VDyv6L2wX0TdXs8rWfToKcXVke9oJaspE27CWoLFrGbwgFCxkuaVDMKxMZ6EHp +TOiaX3yskunX8YiekfmeDqjYUMhFfp9xMUhjtDWMokchwHmQREIv0pzwZhbwCnIelkrQxwKmzmUj +TSlhLZ1lACa5Oww59gfRCGm0w0ehN9Nfvlyh7TAlKLnRUWsIt6HErGQBtAFkC22QRKIIkam0iAgO +M+g2laUXpsPgzHVVSgufxEfuFNJ0JVgyj+vJOHnUI5IHQoYlrSI5p+EeGMJhURBNurWFhNJSjHOo +iWoBp/GE+UpKs2sYBJzTDuylNvDeO48jHhKoun/aSHwhqsvRyaeQB2l1bwvTSKYuUFWGFGmfturI +SJmYU3EEW/+ZB5Dn1zI25j4PanimpWDcr9amcqH2OGHbDGBc8WwahEyLhzBUqvuERM2LbmKb5XYs +e1vVVjQyikCgAxVH1uulG5oiW8JZcBITA8zwmGgi1bk0+20tTfwjzxA2G7Qj3Q4Wa4unJ6ItXKdR +Jqe3mve2S3hl4i4qgMgxVoCfzESLsvvm0QnIYObFvRw7VVm4JMaYe2+Dd3qEEc7citp5Z0wRAh3h +WHxEX6f2/BhKF0tLOPD4ffkuyWAutTBbAu28Fe45RTsYYIFKAhTE/yw+jgS09UZKdvmrkNq55Tnx +Pjcy1svK1hUZ8c1TmQUbCx7WvGmfb3U5Gu4z/Ad6IIn6DgCmYcUm4WKNjGMn/n82XlBOa/8YgMt8 +3cLAdgQYAQgAIBYhBDtD89a/PyOnIzH9TWyXZJPEYz+1BQI7msoAAhsMAAoJEGyXZJPEYz+1h4QH +/1K/37H0kkCn7ehXgmj2ls5324J8JdA10m/4FM2QDEwBMHy0v+C8csIieam1YUX+TewsD9H28oOV +WRWGvOrdeYloXqjgFBWbmdDRLGKaslZBm1udK8bh1Px6bNOa6h+N2lCCScs6cZ3Z4gTMQXpQfEKG +1545lCve4sNHvbqDIj4/mqks8lv3nB3cAy8ichbN4wdZEUlAnGRFLWVWt4o9jUp2PizspF4kX/th +sprqDzOpSRuSgixQ/kkBAaRZNU04mkIIFs95z7tcalAzsdjIwKSwxe0/6ywksdbuFmuOVc8d7U35 +vLztBNmIjxaQB2fgTF5SoLLafe2IQmCTecy4LJY= +=gTGj +-----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-sub-crit-note-pub.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-sub-crit-note-pub.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-sub-crit-note-sec.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_edge_cases/key-sub-crit-note-sec.pgp differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_validity/case5/generate.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_validity/case5/generate.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_validity/case5/generate.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_validity/case5/generate.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -41,12 +41,12 @@ return res; } -bool calculate_primary_binding(const pgp_key_pkt_t *key, - const pgp_key_pkt_t *subkey, +bool calculate_primary_binding(const pgp_key_pkt_t &key, + const pgp_key_pkt_t &subkey, pgp_hash_alg_t halg, - pgp_signature_t * sig, - pgp_hash_t * hash, - rng_t * rng); + pgp_signature_t & sig, + rnp::Hash & hash, + rnp::RNG & rng); int main(int argc, char **argv) @@ -98,22 +98,18 @@ binding->palg = tskey.key.alg; binding->set_keyfp(keyfp); - pgp_hash_t hash = {}; - pgp_hash_t hashcp = {}; + /* This requires transition to rnp::Hash once will be used */ + rnp::Hash hash; + rnp::Hash hashcp; - if (!signature_fill_hashed_data(binding) || - !signature_hash_binding(binding, &tpkey.key, &subkey->subkey, &hash) || + binding->fill_hashed_data(); + if (!signature_hash_binding(binding, &tpkey.key, &subkey->subkey, &hash) || !pgp_hash_copy(&hashcp, &hash)) { RNP_LOG("failed to hash signature"); return 1; } - rng_t rng = {}; - if (!rng_init(&rng, RNG_SYSTEM)) { - RNP_LOG("RNG init failed"); - return 1; - } - + rnp::RNG rng(rnp::RNG::Type::System); if (signature_calculate(binding, &tskey.key.material, &hash, &rng)) { RNP_LOG("failed to calculate signature"); return 1; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-pub.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-pub.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-pub.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-pub.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,26 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsBNBGDN004BCAC36d974nRKfeDqUjRL2DcTyKpc/MJGoGsBsAKPUayra23a0PZliH4jvfDLXU0w +fsUmf9jEMi47j9/mIR3+A+wcanR6/VFahaA2OikakLfjQCJsIW649QJxyBWlDgl4ZZwVwomgRk58 +dmbODA7XTdjUP5YOs+Jweqe4fjUyggkjbJ7YtEOOw8DgUallMvb/XwjimCiM72mYrW2yS2uLdeet +nrpI81nLZ7I8KXamN+KOUqRQBDYJ4TfPW0yUm39onAPvInb8ufg0soakVNkdu+zw7VOrkcmf5lLz +1Cy7CWlkQXHeiJXCRBJgCDDO2OdXX9CQBTWEPJUJijALHAz6WSVdABEBAAHNDXJzYV9zbWFsbF9z +aWfCwIgEEwEIADMWIQQWeYvrPYfh3qbRJf3tI7AQWUfygwUCYM3TTgIbAwULCQgHAgYVCAkKCwIF +FgIDAQAACgkQ7SOwEFlH8oNs+gf493MI+AkpioPOua8d7WGUD5dDMhJiRMpPfGuZT9AGirLDMN07 +Cbyxr0k+4Nj7+J3P6rhApGobHLihYO9dtRbkFSjYRtO77zu76SfNZeaUsq5AMh2w7y4GUL6fJreY +mhJD0RBsplh/lGCga+Nm2N3zzkGI0P9qwZx+ICManutwi4i91nCEE6pfOcaEhbe05/AinxFqG07k +g/JKwFq979QOsAXqsRBa+EbHDfoZIcBr98vX1GW60B2Fnz/8DvXtzhLD8a84SkP2/eMmtV5dqQ3n +NS09/hVg+nl6YYS/3wP0XbKGyp3wvbi6Ol/6NS2H7NwaayJp57+HSU6oKq2MmvJrzsBNBGDN004B +CACqc6kbG+bcrF1QADvb9UuveoLLvtpM+o3TTNvUKeADikNkCQ4eoFPOiFZW+IT5gx26Fpg7wd51 +CJp4G4FRHdyqJKz6WvImG9zuhWW2WIvQ5W613C799S/pYY0tEw2cW+eZwrv7FhuXuru/Bb2pt4X/ +977eFHDBJ3q1i0e/LHFVIPdSIvSF+DyveOboWMw9C2htDIXj+tAhvbCTtXVgDuvdqq3UX5xi09F6 +dLSs3M1YmqOp8xDMUiNCpJ51rARqYFl6eiPUsGwk7Z0On72bxC61bkuwxjR1LLtjhkhSVlTztteh +5jwhRPbdugU7JVB6APwrboFnyykZ5dABL1UaU4wTABEBAAHCwHYEGAEIACAWIQQWeYvrPYfh3qbR +Jf3tI7AQWUfygwUCYM3TTgIbDAAKCRDtI7AQWUfyg+xcCACHageLUXJhoq3u888JBOCd2mDZ4Zwq +CxFVHy3pDPWvMJbQzdv2SzQBf9egT6oD2eIHoIIn9Fyf7ooe2czSvARZT+tkoFKOg/GAD5mJoT3H +10E2Q75begS63YVKtahN2BeEm6AhqrOT8mOJvO1GJVMAY69uni8K64Pmb1DNERMdTK4S48jc3Qi3 +CzeaKC/DfqnoqQalfYsJEIJUk/SXekZM01yQjpNTgQpXFbHQoilXhILU1mWzQsHobfTTdysGBAp8 +RsyBysCJTrDc9SyCj2oPXKrgQODfEY4HCuM/T4a4lANjn2HQ7F/jAcGuL6F4is6qCWYcRUaj1Mpa +WoOBvSDo +=SEyg +-----END PGP PUBLIC KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-sec.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-sec.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-sec.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_key_validity/rsa_key_small_sig-sec.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,48 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +xcLYBGDN004BCAC36d974nRKfeDqUjRL2DcTyKpc/MJGoGsBsAKPUayra23a0PZliH4jvfDLXU0w +fsUmf9jEMi47j9/mIR3+A+wcanR6/VFahaA2OikakLfjQCJsIW649QJxyBWlDgl4ZZwVwomgRk58 +dmbODA7XTdjUP5YOs+Jweqe4fjUyggkjbJ7YtEOOw8DgUallMvb/XwjimCiM72mYrW2yS2uLdeet +nrpI81nLZ7I8KXamN+KOUqRQBDYJ4TfPW0yUm39onAPvInb8ufg0soakVNkdu+zw7VOrkcmf5lLz +1Cy7CWlkQXHeiJXCRBJgCDDO2OdXX9CQBTWEPJUJijALHAz6WSVdABEBAAEAB/sE7MtiSucoU4Sh +YcAqw8h9zCLbyJz/PS6AZhE7e0lvcboIYQ4oG+ac2GpJV99ITCzFYikQ3/Mi/zBUvlBKTBqXjDZA +UOZL0UZADYCqSHPULxR85sxLQaxmFaCWwfB4++eZIZOD6j4R0S3hmKsREvGahXVkQWbv8ijppN+R +0a+i9ir/nN3DRtyE/5UNpY8BOtyd3Bi1+gKxxubAztRoe+Y5ewiXh6XtjaIe4D8OIFUkf4yn9ZL+ +kB1Bh1C/Pb0iRJNiuEkbzCOtpQbrOt/AAp07ZlafeCpNyTmSz+T9M2dpkG+nqblxGsDNptjP//gf +esoT3qNVgNas53YRQcFl6w2VBADwyr+LPK4q4zRzmp/4UPBsr85H+2QWQbShXoikWSWcd7G++2ZY +hhXJ1OaEqc3V+E+oy5lLH/tSqV40tlMmBwFEF+n0/X3oQdkgtNBwQ8ITlkPsbcq7KbEZULZnQQpA +IMJS6tzCdCwU3RCyYxeJ7Hvf9jALqaI94EXr/lUhpEOVrwQAw4d8CBcP7T0ivt/tfAN+PZHv3aP2 +4QJtRSYqKuzVzm/xo42yt96L3YjnWX+jxifs7wtQFaIdWgqgt84qiYRdGOxrcOsRi4f4YtW6h6WO +Tuwn3kxlNiUsa6oyE4CmPNCS7VeJPTsaMRcTJCZ/2hHsUadLSaH7Boh/yNTvYBQ7RLMD/1Ux0CXV +bHb9YhcR5L9r4gphvPvRU1nF3rxrrxbjX92xHE916EEBwXkgimD7C3XqcAI8GVyMaGMLqRNHrUof +mckA6wp2gK3RQrIg2PsNfKldOdXygz3OQVl5D6Dt5oL7E9REd6IUTE2xQDSQNf6ovci/zUYbIRDu +jWYYC8rbk9gJRWTNDXJzYV9zbWFsbF9zaWfCwIgEEwEIADMWIQQWeYvrPYfh3qbRJf3tI7AQWUfy +gwUCYM3TTgIbAwULCQgHAgYVCAkKCwIFFgIDAQAACgkQ7SOwEFlH8oNs+gf493MI+AkpioPOua8d +7WGUD5dDMhJiRMpPfGuZT9AGirLDMN07Cbyxr0k+4Nj7+J3P6rhApGobHLihYO9dtRbkFSjYRtO7 +7zu76SfNZeaUsq5AMh2w7y4GUL6fJreYmhJD0RBsplh/lGCga+Nm2N3zzkGI0P9qwZx+ICManutw +i4i91nCEE6pfOcaEhbe05/AinxFqG07kg/JKwFq979QOsAXqsRBa+EbHDfoZIcBr98vX1GW60B2F +nz/8DvXtzhLD8a84SkP2/eMmtV5dqQ3nNS09/hVg+nl6YYS/3wP0XbKGyp3wvbi6Ol/6NS2H7Nwa +ayJp57+HSU6oKq2MmvJrx8LYBGDN004BCACqc6kbG+bcrF1QADvb9UuveoLLvtpM+o3TTNvUKeAD +ikNkCQ4eoFPOiFZW+IT5gx26Fpg7wd51CJp4G4FRHdyqJKz6WvImG9zuhWW2WIvQ5W613C799S/p +YY0tEw2cW+eZwrv7FhuXuru/Bb2pt4X/977eFHDBJ3q1i0e/LHFVIPdSIvSF+DyveOboWMw9C2ht +DIXj+tAhvbCTtXVgDuvdqq3UX5xi09F6dLSs3M1YmqOp8xDMUiNCpJ51rARqYFl6eiPUsGwk7Z0O +n72bxC61bkuwxjR1LLtjhkhSVlTztteh5jwhRPbdugU7JVB6APwrboFnyykZ5dABL1UaU4wTABEB +AAEACACjD2h8BZIyEzZlPQQGpT/VTEbp8NdXgu3AcStvaOvjlxZnEX6Pb+McljK6mp5jL7p1df4G +VK2imitjsTRhzEZ4AgP0sKIsMMWG7Nhju4ttuL7TfSL7Ud6WzfrHXw3LQeRqpO8+AWU+HqZS1IQf +YvDu8SuHulgvf7wVBnwJd9OnkgPYzReDDcrKaHuwYS+NtbsE+KGwhYfbs72WMK9+LkM1q9mFD6U6 +wYGEkUq6jx+xnskNTlgafgVNGA07n9oqvkD/c6tOY7m0uMJ2xV2nMAyb7rsbBmyMvE98GMDGUONm +zFQFBeMGAzuWITIa1ff8Xat9vySPAO9xGtycXFcKlWRBBADjBZru+mp54MmrdK866hFIuKAXH8pv +gWvaIv2KUH8s+Bv0jupHv+PFywjuC+3lx/Gt6wdMkPtkEVbqY07SKNyJ7aHlnUF7bm8eufLqZEUb +gtFS+1IvSifbkYl5k45FOsk938A0B6XkPs3Xjg9M4JYEHg4GqjV/ev+KtU7QTzh/4QQAwDWDpa+Y +b2wa9eLH2GbgsLkVgF9s6xvr7ji0AfsNYtHIM/cqS6GZdYCsKu4ygHv1wl2hr7S2mBQdbPmvOcyi +SQD9hSWIP3kZs5c0UGc3+mRYjFT3ujxInFBrrk6649UrR20aUQs6EiMyU++mp/cpqXCLX3OYC55o +g/5zUHqdWnMEALLd8yE8D7UgGC50oCXTRRhWx+jZml/YpUtqR3XeANfdSeeKR2VHS/HzQ7bT4MsV ++1nz9yxaDGQH3Swj+3mIYAceWn97xnPu0VrarOab1Tl8c97/0SQPcwIh/kTTrNGHmLTFuMeudVyx +FMNsUlNKJdhwekPm/eTy2IYtUFXpubo8QqzCwHYEGAEIACAWIQQWeYvrPYfh3qbRJf3tI7AQWUfy +gwUCYM3TTgIbDAAKCRDtI7AQWUfyg+xcCACHageLUXJhoq3u888JBOCd2mDZ4ZwqCxFVHy3pDPWv +MJbQzdv2SzQBf9egT6oD2eIHoIIn9Fyf7ooe2czSvARZT+tkoFKOg/GAD5mJoT3H10E2Q75begS6 +3YVKtahN2BeEm6AhqrOT8mOJvO1GJVMAY69uni8K64Pmb1DNERMdTK4S48jc3Qi3CzeaKC/Dfqno +qQalfYsJEIJUk/SXekZM01yQjpNTgQpXFbHQoilXhILU1mWzQsHobfTTdysGBAp8RsyBysCJTrDc +9SyCj2oPXKrgQODfEY4HCuM/T4a4lANjn2HQ7F/jAcGuL6F4is6qCWYcRUaj1MpaWoOBvSDo +=0M+o +-----END PGP PRIVATE KEY BLOCK----- \ No newline at end of file diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/data.enc.small-rsa thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/data.enc.small-rsa --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/data.enc.small-rsa 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/data.enc.small-rsa 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,10 @@ +-----BEGIN PGP MESSAGE----- + +wcBLAzLESw+ElNMdAQf3SMPGDe5lDEHwnmoA4yZiSlECdXbfZ4rkMcWbxlcsmNLHR4LcMdWi9+fP +pxTHZmaAVRCpMHpZ0TNt3d5TyaHD0/qitJLHAq847jE5HeS+naguPRKYdjCsXUpC5dd5+5Inj3YB +PRMk7cP/0vgB66X0E8ebVB92Yp+Azs9/I1+hdFoAMGs9wfli0OkvIxySsjeASXj4W4v2WVl8eOOD +LePAta6QPtvBT/9+ImMgBtV4A+zPuvofIMD25SeqPCTaWCjJs6oO/lUIfcByzoEQ2fGJvmkvQ0lU +ZI1DfSmn2cuRQqr3CjY/9MfYtOR85rZUqBR9i8F19vtZU4J+QzYAkuOS0jYBM6DWkZ36znNchLYd +gCR9Pl8XdI786rkQefmJh+2zjPkdcq/jx/df5T7kyJKW3uJm3Z/hs+Q= +=I1qv +-----END PGP MESSAGE----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message-trailing-cr.txt thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message-trailing-cr.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message-trailing-cr.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message-trailing-cr.txt 2022-04-15 07:49:22.000000000 +0000 @@ -1,3 +1,3 @@ Text line with 3 trailing CR characters Another line with CR at the beginning, should not be stripped. -Last line with trailing CR and no LF. \ No newline at end of file +Last line with trailing CR and no LF. \ No newline at end of file Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.enc-eg-bad and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.enc-eg-bad differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.enc-eg-bad2 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.enc-eg-bad2 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.enc-sign-25519 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.enc-sign-25519 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed.crit-notation and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed.crit-notation differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed.md5 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed.md5 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-md5-after and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-md5-after differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-md5-before and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-md5-before differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed.sha1 and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed.sha1 differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sha1-after and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sha1-after differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sha1-before and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sha1-before differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sym-none-z thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sym-none-z --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sym-none-z 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.signed-sym-none-z 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,2 @@ +  K1F0g|ׄTRB]Gz (hŀ#Usތg{ڎ*Cnm_q^#k t9P2}`XKRZZ+hD#^ *mU%/2yyV<>@ YTi S4;ģ@>ؚ4?&ky&>l,.`R$=V$^S?\Q $p\Y˜Nft;ssT ~6r6Ù|]);1*p"Zr!ar \ No newline at end of file Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/message.txt.sign-small-eddsa-x and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/message.txt.sign-small-eddsa-x differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/shattered-1.pdf and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/shattered-1.pdf differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/shattered-1.pdf.sig and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/shattered-1.pdf.sig differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/shattered-2.pdf and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/shattered-2.pdf differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_messages/shattered-2.pdf.gpg and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_messages/shattered-2.pdf.gpg differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_stream_key_load/g10/pubring.kbx and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_stream_key_load/g10/pubring.kbx differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-pub.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-pub.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-pub.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-pub.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBGHFpKQBCAC5ECPljro7upeEP8pR8SYW3qymdJhC5Fv0sj94Sg+mst5e6ob6 +nqEDd4oUc+Y4FSuivdJCdj9kRKDnbKj4qAFp/liC3su7FJ0fS32pdR9vVaWelJDF +mdtWpvhEPAninnUakPxHIHgDSkKUtgwbvrIZxumdxA/du9N6RWyXw3gnawBK+7bz +1HpjYooRFhjd/YQ2G5Bm9x6i9TDY321BCDZdKF1xsEnCjs+cUrAwqJdAqcNNyZP/ +tdfR9UlLSIGqlFT7CMo97tAD9+uKd9OMv0SabTg23L0AV9sq2HvrrigFgRlNFjLl +2xGNDGhs9qhi/IBQFFBoFcTcjKRPCU0C+6ThABEBAAG0CXJzYS1yc2EtMokBUgQT +AQgAPBYhBFqpNirqB94jpyZ2LL2GClLRiZwPBQJhxaSkAhsDBQsJCAcCAyICAQYV +CgkICwIEFgIDAQIeBwIXgAAKCRC9hgpS0YmcDzkDB/4zz6LACglpAvpFK0P4L4oO +s4BiwDl7xXqgOfgbc/zRtlx6iOitT78+tf+6/tuA+3HjtF7CQqONpc9xjiQjK0BL +R0N2YR23OBWCzb0hhxmueV6TtDNZkM8aZQdeAjEaMVKiDY4nVF+I0HVyl6AON+2c +BrU0abio8kBP8XXoSFdPu9QefdNojpNs6+/enItFFD0n6Jhn6zXlo0c0T3dCBL+H +ckiJYTV/WGYzYXfowVn/GCddOysndnCZ5vXLO5xKgSf8X7D+wI/jG+tqU5qa7Usw +fytM1B0zrP784Ke2S/V+PgofiTzPI8G5KDXofqiZoIDV3eRpiG3Ry/JOwbF/Yg8H +uQENBGHFpKQBCAC4ySoNlCNm3N0ijhufLPx+qesBYt7uW8ihJwKa3fUFVsdaPjdp +/8tBT5I9QIjrZHSs55Hkug0v/CpKeuIsk27XIplsf0A/80QQ3sQEP8NtAeHQU13U +Vg1XpfHuox+Qd91aJ0VElRd+5n+ZC6nx8jBvAUcscXLD8lmAOaOxhpluRC2Yy9ah +wy51IlpZSAiYBKCbZ6hxdr0zf6Gjjo47UKLWJ60VBL9AQNZo/alDkQo2W+NDlQp1 +R0dnAL/kSEjaMPiE+Y29VynExqdSbwI2m+nzfd6m5zcQ/7QpDzz2DPV9xz52iBCO +nJUSdBbc3IkoJR1y1QwleoKTegZUJy2mblZFABEBAAGJATYEGAEIACAWIQRaqTYq +6gfeI6cmdiy9hgpS0YmcDwUCYcWkpAIbDAAKCRC9hgpS0YmcD0TKCACIoCQInxDa +P0pQXLwu+uWvivEF2oGUNGpxkqZBySgSJF1wBbPX8CCj64GqJ4WGch/QJKZI2wTZ +9+MCV1488AoUOYPTSdpvT0tHHFZIUUgo/uxwy3+0+6Yf3vd8c82Y1lKz1AwHebcE +NSJNgv+KakOfgSVMtk/lt+u4sOaPqc2821HC+wis3+VHyd2ecmSzfdFeR8iUpuui +2Y4nuu6j2OGwz1m/vQ1LES4/bG1bwqTqgEfHxH6Z2KZGdUa9LXe0df9VeOBPtyXo +yaTG8azI4z9bxjE+Rex9y14WHipPkvWVPwSfynphiTPLsTx6vlD94FaDOf7tb5Ys +XJ0kLaL3H0Vh +=/D6t +-----END PGP PUBLIC KEY BLOCK----- diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-sec.asc thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-sec.asc --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-sec.asc 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-2-sec.asc 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,59 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQPGBGHFpKQBCAC5ECPljro7upeEP8pR8SYW3qymdJhC5Fv0sj94Sg+mst5e6ob6 +nqEDd4oUc+Y4FSuivdJCdj9kRKDnbKj4qAFp/liC3su7FJ0fS32pdR9vVaWelJDF +mdtWpvhEPAninnUakPxHIHgDSkKUtgwbvrIZxumdxA/du9N6RWyXw3gnawBK+7bz +1HpjYooRFhjd/YQ2G5Bm9x6i9TDY321BCDZdKF1xsEnCjs+cUrAwqJdAqcNNyZP/ +tdfR9UlLSIGqlFT7CMo97tAD9+uKd9OMv0SabTg23L0AV9sq2HvrrigFgRlNFjLl +2xGNDGhs9qhi/IBQFFBoFcTcjKRPCU0C+6ThABEBAAH+BwMCcUyCWs2sCnzyO07d +hwrWm5GuUIxyqAPOydAoZPlPKC+KMDPSZsFeKMawjW4rMfbHoHw9W2wHpDS4Ocsx +nC3cZkXxtMV1s9BFqseyiifOtJBavUWzkJv7aLYgjlOlXzmtXc0SzLm+ojxn//na +hXlyx2RvwSZ+qKvYNnoC89d8uAnkreOux22SeGB5rY8vsLcJ//5wdL040XEx3w3c +6tm6HDDJ/apHUxaiYAimb00Ghx3j5rcr8Ls3CT0IcWfoGQ0mrOVwOODJh3oUFgSw +WAwtMpA1EGdObchjhT1OMO7H6V8AQk0l27mOrmSHzMXanZAi0NUp64s50/tYRHMt +7XYRLKyffBcqVLQRScNo89Y5O6X2+duWTwuEzJ5FsiYQLh9V0UAa2B98oaGsahUT +il74RajZGZWWQYw1DWDbq8ygvKhk5WUybapoIar8Xigb/QwGiWCHppriKg8OwxnL +M6e+i0BWKBs9x+7Zy5Ia8L+iXor1OknipGsdE4D4DOAbpxzubfaOISbQjEhuoxz9 +fiQHLsLpe8mejVWvbxL2D5JZSGxYBL/2d0S36JRGXM5wrosOIb063bKRebwoP3eP +X17ov7i+dpXTVAA5vrci3ArDkxmshRPeD9zPhuz3rNoD7je+c5tXCOt7N/RkewrY +ZPF3owjpgitmIHgiodBvjbjO0j/Mo/EdiErYKYlyPp/RRMkWNN3OGOk1mFWJq4ZU +hjX61CU0OCSEDvvYfRAaJ5KqvplgwyHhRk7lfdTARWqbJjRuEeXdYMbPpxO7t70J +cu49c2NSeqhlB/U2EsbhRoFM+pexvLC9S49b7LYz9ynR+bw+JBfPbMY7c7/RHAUO +lQTBYKsvDbc2+Wv+ghxF/jURCLBB+Cq25uuCRhrt1z3BT06Uap7WVC0POauCmHh8 +P0IkfzAsVsHPtAlyc2EtcnNhLTKJAVIEEwEIADwWIQRaqTYq6gfeI6cmdiy9hgpS +0YmcDwUCYcWkpAIbAwULCQgHAgMiAgEGFQoJCAsCBBYCAwECHgcCF4AACgkQvYYK +UtGJnA85Awf+M8+iwAoJaQL6RStD+C+KDrOAYsA5e8V6oDn4G3P80bZceojorU+/ +PrX/uv7bgPtx47RewkKjjaXPcY4kIytAS0dDdmEdtzgVgs29IYcZrnlek7QzWZDP +GmUHXgIxGjFSog2OJ1RfiNB1cpegDjftnAa1NGm4qPJAT/F16EhXT7vUHn3TaI6T +bOvv3pyLRRQ9J+iYZ+s15aNHNE93QgS/h3JIiWE1f1hmM2F36MFZ/xgnXTsrJ3Zw +meb1yzucSoEn/F+w/sCP4xvralOamu1LMH8rTNQdM6z+/OCntkv1fj4KH4k8zyPB +uSg16H6omaCA1d3kaYht0cvyTsGxf2IPB50DxgRhxaSkAQgAuMkqDZQjZtzdIo4b +nyz8fqnrAWLe7lvIoScCmt31BVbHWj43af/LQU+SPUCI62R0rOeR5LoNL/wqSnri +LJNu1yKZbH9AP/NEEN7EBD/DbQHh0FNd1FYNV6Xx7qMfkHfdWidFRJUXfuZ/mQup +8fIwbwFHLHFyw/JZgDmjsYaZbkQtmMvWocMudSJaWUgImASgm2eocXa9M3+ho46O +O1Ci1ietFQS/QEDWaP2pQ5EKNlvjQ5UKdUdHZwC/5EhI2jD4hPmNvVcpxManUm8C +Npvp833epuc3EP+0KQ889gz1fcc+dogQjpyVEnQW3NyJKCUdctUMJXqCk3oGVCct +pm5WRQARAQAB/gcDAoc73qUs0Lce8v7NfBna4u/Tq0OQDPQ6u/JxoUmeYNkHzLYK +8qzO0JlwiI534WcxvfelSreMIC7JrqFnbO75GHrjZbWut1d8cg+KjH3JOFseMUVe +vQB0ouCmsbAZlIDEpFI/NkEjQMchk1R7Yw0hSvgKqi1M3KnMUxFPf5GW4R6uVYig +gh0J2Do8gExoTigoww03CyfHTjJALP4q1RVsq4kQVYOv5b6deHmtoTTcRX1+oe9u +uT/Sm75M0SG5F54vUtcNFwXIVRUOxLAMvbSqTNSmekDd41ZNPkfd++q+Z5mYq3jW +Wz3LmEc1WFjc8gG1HgxthJGJJQ17TFLPcaVdqor+163mw+0Q5B7YJ/laVYKtRm2L +viM9zwAX9RZ0wKM42CFZprDG8xfyOFsGMDrJh4zrsl8ctRmLrIrBl+uDEu7cd1q8 +c8vej+YsP3HN9+1UHggSYyLHoxo6PrWSt3XZWGdscPxRDACp5GyNsLTimQgwVDxg +5mNOI9A0iJwjocjQ91XYU0Ve3sx2K46+CMrUm0qDzlgzB+iRi+XACHQ9oYEyWUkk +0m/VHL0HPOi3QrIDjHdqilSRA6hPnFyjckxLfvDhZG2vXPG9LCaVV0mYSy6VvGYp +XUsisUvLDahYYS035hds2tGTYj3NQdltNGVOww98HOmHjYWUcYOAjVDZXLzLTlzf +F/NLIYdW+3tz7u2MC76bvD2RdihzwV/TVIln+P/N3sSajxeR0/6ZqiVcV5cfLfAR +Dc/4IBlXxICRX4dMWRs7i4KqLpgf+SqJFummNXHjR0bxnlbSVAHUnmX3D5puaZkA +IjCtUIeofqqrUedxEyM8FUw0HlrJvqLHAjgeURq6O5u91G8B86NSCPMmFuXful4Y +9OXixgcStbwf5WcFiPJ8qbGsGgVItuVEEnaOprnMYCOjIokBNgQYAQgAIBYhBFqp +NirqB94jpyZ2LL2GClLRiZwPBQJhxaSkAhsMAAoJEL2GClLRiZwPRMoIAIigJAif +ENo/SlBcvC765a+K8QXagZQ0anGSpkHJKBIkXXAFs9fwIKPrgaonhYZyH9Akpkjb +BNn34wJXXjzwChQ5g9NJ2m9PS0ccVkhRSCj+7HDLf7T7ph/e93xzzZjWUrPUDAd5 +twQ1Ik2C/4pqQ5+BJUy2T+W367iw5o+pzbzbUcL7CKzf5UfJ3Z5yZLN90V5HyJSm +66LZjie67qPY4bDPWb+9DUsRLj9sbVvCpOqAR8fEfpnYpkZ1Rr0td7R1/1V44E+3 +JejJpMbxrMjjP1vGMT5F7H3LXhYeKk+S9ZU/BJ/KemGJM8uxPHq+UP3gVoM5/u1v +lixcnSQtovcfRWE= +=EEQP +-----END PGP PRIVATE KEY BLOCK----- Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_validate_key_material/eg-sec-small-group-enc.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_validate_key_material/eg-sec-small-group-enc.pgp differ Binary files /tmp/tmp9lrgb0gz/ut_KmsdcfE/thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_validate_key_material/eg-sec-small-group.pgp and /tmp/tmp9lrgb0gz/5vDmGH_cMB/thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_validate_key_material/eg-sec-small-group.pgp differ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_validate_key_material/readme.txt thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_validate_key_material/readme.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/data/test_validate_key_material/readme.txt 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/data/test_validate_key_material/readme.txt 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,48 @@ +Some of ElGamal samples were generated by using the following custom key generation snippet: + +{ + std::unique_ptr rng; + rng.reset(new Botan::System_RNG); + + Botan::BigInt p = Botan::random_prime(*rng, keybits, 0, 2, 3, 64); + Botan::BigInt p1(p - 1); + Botan::BigInt sg = 1; + Botan::BigInt g; + + size_t mod = 2; + while (mod < 65536) { + if (p1 % mod == 0) { + if (sg * mod > (1 << 16)) { + break; + } + RNP_LOG("Reduced by %zu", mod); + p1 = p1 / mod; + sg *= mod; + continue; + } + mod++; + } + if (Botan::power_mod(3, p - 1, p).cmp_word(1) != 0) { + RNP_LOG("3 ^ (p - 1) != 1 (mod p)"); + goto end; + } + Botan::BigInt ng = Botan::power_mod(3, p1, p); + if (Botan::power_mod(ng, sg, p).cmp_word(1) != 0) { + RNP_LOG("ng ^ sg != 1 (mod p)"); + goto end; + } + g = ng; + + Botan::BigInt x(*rng, keybits, true); + Botan::BigInt y = Botan::power_mod(g, x, p); + + key->p.len = p.bytes(); + p.binary_encode(key->p.mpi); + key->g.len = g.bytes(); + g.binary_encode(key->g.mpi); + key->x.len = x.bytes(); + x.binary_encode(key->x.mpi); + key->y.len = y.bytes(); + y.binary_encode(key->y.mpi); + ret = RNP_SUCCESS; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/exportkey.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/exportkey.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/exportkey.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/exportkey.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -39,11 +39,11 @@ /* Initialize the rnp structure. */ assert_true(setup_cli_rnp_common(&rnp, RNP_KEYSTORE_GPG, NULL, pipefd)); /* Generate the key */ - cli_set_default_rsa_key_desc(cli_rnp_cfg(rnp), "SHA256"); + cli_set_default_rsa_key_desc(rnp.cfg(), "SHA256"); assert_true(cli_rnp_generate_key(&rnp, NULL)); /* Loading keyrings and checking whether they have correct key */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); size_t keycount = 0; assert_rnp_success(rnp_get_public_key_count(rnp.ffi, &keycount)); assert_int_equal(keycount, 2); @@ -65,5 +65,5 @@ if (pipefd[0] != -1) { close(pipefd[0]); } - cli_rnp_end(&rnp); // Free memory and other allocated resources. + rnp.end(); // Free memory and other allocated resources. } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -35,9 +35,8 @@ #include "librepgp/stream-packet.h" #include "librepgp/stream-sig.h" #include -#include -#include #include "file-utils.h" +#include "str-utils.h" #include #include "pgp-key.h" #include "ffi-priv-types.h" @@ -52,12 +51,24 @@ // get the default homedir (not a very thorough test) { + assert_rnp_failure(rnp_get_default_homedir(NULL)); char *homedir = NULL; assert_rnp_success(rnp_get_default_homedir(&homedir)); assert_non_null(homedir); rnp_buffer_destroy(homedir); } + // check NULL params + assert_rnp_failure( + rnp_detect_homedir_info(NULL, &pub_format, &pub_path, &sec_format, &sec_path)); + assert_rnp_failure( + rnp_detect_homedir_info("data/keyrings/1", NULL, &pub_path, &sec_format, &sec_path)); + assert_rnp_failure( + rnp_detect_homedir_info("data/keyrings/1", &pub_format, NULL, &sec_format, &sec_path)); + assert_rnp_failure( + rnp_detect_homedir_info("data/keyrings/1", &pub_format, &pub_path, NULL, &sec_path)); + assert_rnp_failure( + rnp_detect_homedir_info("data/keyrings/1", &pub_format, &pub_path, &sec_format, NULL)); // detect the formats+paths assert_rnp_success(rnp_detect_homedir_info( "data/keyrings/1", &pub_format, &pub_path, &sec_format, &sec_path)); @@ -67,6 +78,12 @@ // check paths assert_string_equal(pub_path, "data/keyrings/1/pubring.gpg"); assert_string_equal(sec_path, "data/keyrings/1/secring.gpg"); + // setup FFI with wrong parameters + assert_rnp_failure(rnp_ffi_create(NULL, "GPG", "GPG")); + assert_rnp_failure(rnp_ffi_create(&ffi, "GPG", NULL)); + assert_rnp_failure(rnp_ffi_create(&ffi, NULL, "GPG")); + assert_rnp_failure(rnp_ffi_create(&ffi, "ZZG", "GPG")); + assert_rnp_failure(rnp_ffi_create(&ffi, "GPG", "ZZG")); // setup FFI assert_rnp_success(rnp_ffi_create(&ffi, pub_format, sec_format)); // load our keyrings @@ -177,6 +194,16 @@ size_t data_size = 0; char * format = NULL; + // Wrong parameters + data = NULL; + format = NULL; + load_test_data("keyrings/1/pubring.gpg", &data, &data_size); + assert_rnp_failure(rnp_detect_key_format(NULL, data_size, &format)); + assert_rnp_failure(rnp_detect_key_format((uint8_t *) data, 0, &format)); + assert_rnp_failure(rnp_detect_key_format((uint8_t *) data, data_size, NULL)); + free(data); + free(format); + // GPG data = NULL; format = NULL; @@ -321,6 +348,12 @@ // load assert_rnp_success(rnp_input_from_memory(&input, buf, buf_len, true)); assert_non_null(input); + // try wrong parameters + assert_rnp_failure(rnp_load_keys(NULL, "GPG", input, RNP_LOAD_SAVE_SECRET_KEYS)); + assert_rnp_failure(rnp_load_keys(ffi, NULL, input, RNP_LOAD_SAVE_SECRET_KEYS)); + assert_rnp_failure(rnp_load_keys(ffi, "GPG", NULL, RNP_LOAD_SAVE_SECRET_KEYS)); + assert_rnp_failure(rnp_load_keys(ffi, "WRONG", input, RNP_LOAD_SAVE_SECRET_KEYS)); + assert_rnp_failure(rnp_load_keys(ffi, "WRONG", input, 0)); assert_rnp_success(rnp_load_keys(ffi, "GPG", input, RNP_LOAD_SAVE_SECRET_KEYS)); rnp_input_destroy(input); input = NULL; @@ -422,6 +455,11 @@ pub_path = rnp_compose_path(temp_dir, "pubring.gpg", NULL); assert_false(rnp_file_exists(pub_path)); assert_rnp_success(rnp_output_to_path(&output, pub_path)); + assert_rnp_failure(rnp_save_keys(NULL, "GPG", output, RNP_LOAD_SAVE_PUBLIC_KEYS)); + assert_rnp_failure(rnp_save_keys(ffi, NULL, output, RNP_LOAD_SAVE_PUBLIC_KEYS)); + assert_rnp_failure(rnp_save_keys(ffi, "GPG", NULL, RNP_LOAD_SAVE_PUBLIC_KEYS)); + assert_rnp_failure(rnp_save_keys(ffi, "WRONG", output, RNP_LOAD_SAVE_PUBLIC_KEYS)); + assert_rnp_failure(rnp_save_keys(ffi, "GPG", output, 0)); assert_rnp_success(rnp_save_keys(ffi, "GPG", output, RNP_LOAD_SAVE_PUBLIC_KEYS)); assert_rnp_success(rnp_output_destroy(output)); output = NULL; @@ -1635,6 +1673,11 @@ /* generate sm2 key */ rnp_key_handle_t key = NULL; + if (!sm2_enabled()) { + assert_rnp_failure(rnp_generate_key_sm2(ffi, "sm2", NULL, &key)); + assert_rnp_success(rnp_ffi_destroy(ffi)); + return; + } assert_rnp_success(rnp_generate_key_sm2(ffi, "sm2", NULL, &key)); assert_non_null(key); /* check properties of the generated key */ @@ -1976,34 +2019,52 @@ assert_rnp_success(rnp_key_handle_destroy(subkey)); assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ECDSA")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP256r1")); assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "AES128")); assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "SHA1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); - assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); + if (brainpool_enabled()) { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP256r1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } else { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "brainpoolP256r1")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + } assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ECDSA")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP384r1")); assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "AES128")); assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "SHA1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); - assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); + if (brainpool_enabled()) { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP384r1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } else { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "brainpoolP384r1")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + } assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ECDSA")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP512r1")); assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "AES128")); assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "SHA1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); - assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); + if (brainpool_enabled()) { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP512r1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } else { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "brainpoolP512r1")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + } assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ECDSA")); assert_rnp_success(rnp_op_generate_set_curve(keygen, "secp256k1")); @@ -2027,8 +2088,12 @@ assert_rnp_success(rnp_op_generate_destroy(keygen)); assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ECDSA")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "SM2 P-256")); - assert_rnp_failure(rnp_op_generate_execute(keygen)); + if (!sm2_enabled()) { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "SM2 P-256")); + } else { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "SM2 P-256")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + } assert_rnp_success(rnp_op_generate_destroy(keygen)); /* Add EDDSA subkey */ @@ -2098,15 +2163,19 @@ assert_rnp_success(rnp_key_handle_destroy(subkey)); /* Add SM2 subkey */ - assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "SM2")); - assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "AES128")); - assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "SHA1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); + if (!sm2_enabled()) { + keygen = NULL; + assert_rnp_failure(rnp_op_generate_subkey_create(&keygen, ffi, key, "SM2")); + } else { + assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "SM2")); + assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "AES128")); + assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "SHA1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); - assert_rnp_success(rnp_key_handle_destroy(key)); assert_rnp_success(rnp_ffi_destroy(ffi)); } @@ -2239,34 +2308,52 @@ assert_rnp_success(rnp_key_handle_destroy(subkey)); assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ecdsa")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP256r1")); assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "aes128")); assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "sha1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); - assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); + if (brainpool_enabled()) { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP256r1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } else { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "brainpoolP256r1")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + } assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ecdsa")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP384r1")); assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "aes128")); assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "sha1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); - assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); + if (brainpool_enabled()) { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP384r1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } else { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "brainpoolP384r1")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + } assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ecdsa")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP512r1")); assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "aes128")); assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "sha1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); - assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); + if (brainpool_enabled()) { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "brainpoolP512r1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } else { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "brainpoolP512r1")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_destroy(keygen)); + } assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ecdsa")); assert_rnp_success(rnp_op_generate_set_curve(keygen, "secp256k1")); @@ -2278,7 +2365,7 @@ assert_rnp_success(rnp_op_generate_destroy(keygen)); assert_rnp_success(rnp_key_handle_destroy(subkey)); - /* These curves will not work with ECDSA*/ + /* These curves will not work with ECDSA */ assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ecdsa")); assert_rnp_success(rnp_op_generate_set_curve(keygen, "Ed25519")); assert_rnp_failure(rnp_op_generate_execute(keygen)); @@ -2290,8 +2377,12 @@ assert_rnp_success(rnp_op_generate_destroy(keygen)); assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "ecdsa")); - assert_rnp_success(rnp_op_generate_set_curve(keygen, "SM2 P-256")); - assert_rnp_failure(rnp_op_generate_execute(keygen)); + if (!sm2_enabled()) { + assert_rnp_failure(rnp_op_generate_set_curve(keygen, "SM2 P-256")); + } else { + assert_rnp_success(rnp_op_generate_set_curve(keygen, "SM2 P-256")); + assert_rnp_failure(rnp_op_generate_execute(keygen)); + } assert_rnp_success(rnp_op_generate_destroy(keygen)); /* Add EDDSA subkey */ @@ -2328,15 +2419,19 @@ assert_rnp_success(rnp_key_handle_destroy(subkey)); /* Add SM2 subkey */ - assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "sm2")); - assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "aes128")); - assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "sha1")); - assert_rnp_success(rnp_op_generate_execute(keygen)); - assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); - assert_non_null(subkey); + if (!sm2_enabled()) { + keygen = NULL; + assert_rnp_failure(rnp_op_generate_subkey_create(&keygen, ffi, key, "sm2")); + } else { + assert_rnp_success(rnp_op_generate_subkey_create(&keygen, ffi, key, "sm2")); + assert_rnp_success(rnp_op_generate_set_protection_cipher(keygen, "aes128")); + assert_rnp_success(rnp_op_generate_set_protection_hash(keygen, "sha1")); + assert_rnp_success(rnp_op_generate_execute(keygen)); + assert_rnp_success(rnp_op_generate_get_key(keygen, &subkey)); + assert_non_null(subkey); + assert_rnp_success(rnp_key_handle_destroy(subkey)); + } assert_rnp_success(rnp_op_generate_destroy(keygen)); - assert_rnp_success(rnp_key_handle_destroy(subkey)); - assert_rnp_success(rnp_key_handle_destroy(key)); assert_rnp_success(rnp_ffi_destroy(ffi)); } @@ -2501,9 +2596,19 @@ assert_int_equal(1, count); // protect+lock the key - assert_rnp_success(rnp_key_protect(key_handle, "pass", "SM4", "CFB", "SM3", 999999)); + if (!sm2_enabled()) { + assert_rnp_failure(rnp_key_protect(key_handle, "pass", "SM4", "CFB", "SM3", 999999)); + assert_rnp_success( + rnp_key_protect(key_handle, "pass", "AES128", "CFB", "SHA256", 999999)); + } else { + assert_rnp_success(rnp_key_protect(key_handle, "pass", "SM4", "CFB", "SM3", 999999)); + } assert_rnp_success(rnp_key_lock(key_handle)); + // add with NULL parameters + assert_rnp_failure(rnp_key_add_uid(NULL, new_userid, NULL, 2147317200, 0x00, false)); + assert_rnp_failure(rnp_key_add_uid(key_handle, NULL, NULL, 2147317200, 0x00, false)); + // add the userid (no pass provider, should fail) assert_int_equal( RNP_ERROR_BAD_PASSWORD, @@ -2512,9 +2617,15 @@ // actually add the userid assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "pass")); + // attempt to add empty uid + assert_rnp_failure(rnp_key_add_uid(key_handle, "", NULL, 2147317200, 0, false)); // add with default hash algorithm assert_rnp_success( rnp_key_add_uid(key_handle, default_hash_userid, NULL, 2147317200, 0, false)); + // check whether key was locked back + bool locked = false; + assert_rnp_success(rnp_key_is_locked(key_handle, &locked)); + assert_true(locked); // check if default hash was used assert_rnp_success(rnp_key_get_uid_handle_at(key_handle, 1, &uid)); assert_rnp_success(rnp_uid_get_signature_at(uid, 0, &sig)); @@ -2874,6 +2985,9 @@ // execute the operation assert_rnp_success(rnp_op_sign_execute(op)); // make sure the output file was created + assert_rnp_failure(rnp_output_memory_get_buf(NULL, &signed_buf, &signed_len, true)); + assert_rnp_failure(rnp_output_memory_get_buf(output, NULL, &signed_len, true)); + assert_rnp_failure(rnp_output_memory_get_buf(output, &signed_buf, NULL, true)); assert_rnp_success(rnp_output_memory_get_buf(output, &signed_buf, &signed_len, true)); assert_non_null(signed_buf); assert_true(signed_len > 0); @@ -3373,10 +3487,9 @@ assert_true(check_json_field_int(subpkt, "length", 51)); assert_true(check_json_field_bool(subpkt, "hashed", true)); assert_true(check_json_field_bool(subpkt, "critical", false)); - assert_true(check_json_field_str(subpkt, - "raw", - "800000000021000a73657269616c6e756d62657240646f74732e7465" - "7374646f6d61696e2e7465737454455354303030303031")); + assert_true(check_json_field_bool(subpkt, "human", true)); + assert_true(check_json_field_str(subpkt, "name", "serialnumber@dots.testdomain.test")); + assert_true(check_json_field_str(subpkt, "value", "TEST000001")); /* subpacket 4 */ subpkt = json_object_array_get_idx(subpkts, 4); assert_true(check_json_field_int(subpkt, "type", 26)); @@ -3501,64 +3614,54 @@ jso = json_tokener_parse(json); assert_non_null(jso); // validate some properties - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "type")), "ECDSA"), 0); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "type")), "ECDSA")); assert_int_equal(json_object_get_int(get_json_obj(jso, "length")), 256); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "curve")), "NIST P-256"), 0); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "keyid")), "0E33FD46FF10F19C"), - 0); - assert_int_equal(rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "fingerprint")), - "B6B5E497A177551ECB8862200E33FD46FF10F19C"), - 0); - assert_int_equal(rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "grip")), - "20A48B3C61525DCDF8B3B9D82C6BBCF4D8BFB5E5"), - 0); + assert_true( + rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "curve")), "NIST P-256")); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "keyid")), + "0E33FD46FF10F19C")); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "fingerprint")), + "B6B5E497A177551ECB8862200E33FD46FF10F19C")); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "grip")), + "20A48B3C61525DCDF8B3B9D82C6BBCF4D8BFB5E5")); assert_int_equal(json_object_get_boolean(get_json_obj(jso, "revoked")), false); assert_int_equal(json_object_get_int64(get_json_obj(jso, "creation time")), 1511313500); assert_int_equal(json_object_get_int64(get_json_obj(jso, "expiration")), 0); // usage assert_int_equal(json_object_array_length(get_json_obj(jso, "usage")), 2); - assert_int_equal(rnp_strcasecmp(json_object_get_string(json_object_array_get_idx( - get_json_obj(jso, "usage"), 0)), - "sign"), - 0); - assert_int_equal(rnp_strcasecmp(json_object_get_string(json_object_array_get_idx( - get_json_obj(jso, "usage"), 1)), - "certify"), - 0); + assert_true(rnp::str_case_eq( + json_object_get_string(json_object_array_get_idx(get_json_obj(jso, "usage"), 0)), + "sign")); + assert_true(rnp::str_case_eq( + json_object_get_string(json_object_array_get_idx(get_json_obj(jso, "usage"), 1)), + "certify")); // primary key grip assert_null(get_json_obj(jso, "primary key grip")); // subkey grips assert_int_equal(json_object_array_length(get_json_obj(jso, "subkey grips")), 1); - assert_int_equal(rnp_strcasecmp(json_object_get_string(json_object_array_get_idx( - get_json_obj(jso, "subkey grips"), 0)), - "FFFA72FC225214DC712D0127172EE13E88AF93B4"), - 0); + assert_true(rnp::str_case_eq( + json_object_get_string(json_object_array_get_idx(get_json_obj(jso, "subkey grips"), 0)), + "FFFA72FC225214DC712D0127172EE13E88AF93B4")); // public key assert_int_equal(json_object_get_boolean(get_json_obj(jso, "public key.present")), true); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "public key.mpis.point")), - "04B0C6F2F585C1EEDF805C4492CB683839D5EAE6246420780F063D558" - "A33F607876BE6F818A665722F8204653CC4DCFAD4F4765521AC8A6E9F" - "793CEBAE8600BEEF"), - 0); + assert_true( + rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "public key.mpis.point")), + "04B0C6F2F585C1EEDF805C4492CB683839D5EAE6246420780F063D558" + "A33F607876BE6F818A665722F8204653CC4DCFAD4F4765521AC8A6E9F" + "793CEBAE8600BEEF")); // secret key assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.present")), true); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "secret key.mpis.x")), - "46DE93CA439735F36B9CF228F10D8586DA824D88BBF4E24566D5312D061802C8"), - 0); + assert_true( + rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "secret key.mpis.x")), + "46DE93CA439735F36B9CF228F10D8586DA824D88BBF4E24566D5312D061802C8")); assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.locked")), false); assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.protected")), false); // userids assert_int_equal(json_object_array_length(get_json_obj(jso, "userids")), 1); - assert_int_equal(rnp_strcasecmp(json_object_get_string(json_object_array_get_idx( - get_json_obj(jso, "userids"), 0)), - "test0"), - 0); + assert_true(rnp::str_case_eq( + json_object_get_string(json_object_array_get_idx(get_json_obj(jso, "userids"), 0)), + "test0")); // signatures assert_int_equal(json_object_array_length(get_json_obj(jso, "signatures")), 1); json_object *jsosig = json_object_array_get_idx(get_json_obj(jso, "signatures"), 0); @@ -3581,55 +3684,45 @@ jso = json_tokener_parse(json); assert_non_null(jso); // validate some properties - assert_int_equal(rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "type")), "ECDH"), - 0); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "type")), "ECDH")); assert_int_equal(json_object_get_int(get_json_obj(jso, "length")), 256); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "curve")), "NIST P-256"), 0); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "keyid")), "074131BC8D16C5C9"), - 0); - assert_int_equal(rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "fingerprint")), - "481E6A41B10ECD71A477DB02074131BC8D16C5C9"), - 0); + assert_true( + rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "curve")), "NIST P-256")); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "keyid")), + "074131BC8D16C5C9")); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "fingerprint")), + "481E6A41B10ECD71A477DB02074131BC8D16C5C9")); // ECDH-specific - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "kdf hash")), "SHA256"), 0); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "key wrap cipher")), "AES128"), - 0); - assert_int_equal(rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "grip")), - "FFFA72FC225214DC712D0127172EE13E88AF93B4"), - 0); + assert_true( + rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "kdf hash")), "SHA256")); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "key wrap cipher")), + "AES128")); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "grip")), + "FFFA72FC225214DC712D0127172EE13E88AF93B4")); assert_int_equal(json_object_get_boolean(get_json_obj(jso, "revoked")), false); assert_int_equal(json_object_get_int64(get_json_obj(jso, "creation time")), 1511313500); assert_int_equal(json_object_get_int64(get_json_obj(jso, "expiration")), 0); // usage assert_int_equal(json_object_array_length(get_json_obj(jso, "usage")), 1); - assert_int_equal(rnp_strcasecmp(json_object_get_string(json_object_array_get_idx( - get_json_obj(jso, "usage"), 0)), - "encrypt"), - 0); + assert_true(rnp::str_case_eq( + json_object_get_string(json_object_array_get_idx(get_json_obj(jso, "usage"), 0)), + "encrypt")); // primary key grip - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "primary key grip")), - "20A48B3C61525DCDF8B3B9D82C6BBCF4D8BFB5E5"), - 0); + assert_true(rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "primary key grip")), + "20A48B3C61525DCDF8B3B9D82C6BBCF4D8BFB5E5")); // subkey grips assert_null(get_json_obj(jso, "subkey grips")); // public key assert_int_equal(json_object_get_boolean(get_json_obj(jso, "public key.present")), true); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "public key.mpis.point")), - "04E2746BA4D180011B17A6909EABDBF2F3733674FBE00B20A3B857C2597233651544150B" - "896BCE7DCDF47C49FC1E12D5AD86384D26336A48A18845940A3F65F502"), - 0); + assert_true(rnp::str_case_eq( + json_object_get_string(get_json_obj(jso, "public key.mpis.point")), + "04E2746BA4D180011B17A6909EABDBF2F3733674FBE00B20A3B857C2597233651544150B" + "896BCE7DCDF47C49FC1E12D5AD86384D26336A48A18845940A3F65F502")); // secret key assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.present")), true); - assert_int_equal( - rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "secret key.mpis.x")), - "DF8BEB7272117AD7AFE2B7E882453113059787FBC785C82F78624EE7EF2117FB"), - 0); + assert_true( + rnp::str_case_eq(json_object_get_string(get_json_obj(jso, "secret key.mpis.x")), + "DF8BEB7272117AD7AFE2B7E882453113059787FBC785C82F78624EE7EF2117FB")); assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.locked")), false); assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.protected")), false); @@ -3765,7 +3858,7 @@ ident = NULL; assert_rnp_success(rnp_identifier_iterator_next(it, &ident)); if (ident) { - assert_int_equal(0, rnp_strcasecmp(expected[i], ident)); + assert_true(rnp::str_case_eq(expected[i], ident)); i++; } } while (ident); @@ -3793,7 +3886,7 @@ ident = NULL; assert_rnp_success(rnp_identifier_iterator_next(it, &ident)); if (ident) { - assert_int_equal(0, rnp_strcasecmp(expected[i], ident)); + assert_true(rnp::str_case_eq(expected[i], ident)); i++; } } while (ident); @@ -3816,7 +3909,7 @@ ident = NULL; assert_rnp_success(rnp_identifier_iterator_next(it, &ident)); if (ident) { - assert_int_equal(0, rnp_strcasecmp(expected[i], ident)); + assert_true(rnp::str_case_eq(expected[i], ident)); i++; } } while (ident); @@ -4447,6 +4540,19 @@ assert_true(rnp_version_for(1, 0, 1) > rnp_version_for(1, 0, 0)); assert_true(rnp_version_for(1, 1, 0) > rnp_version_for(1, 0, 1023)); assert_true(rnp_version_for(2, 0, 0) > rnp_version_for(1, 1023, 1023)); + + // commit timestamp + const uint64_t timestamp = rnp_version_commit_timestamp(); + assert_true(!timestamp || (timestamp >= 1639439116)); +} + +TEST_F(rnp_tests, test_ffi_backend_version) +{ + assert_non_null(rnp_backend_string()); + assert_non_null(rnp_backend_version()); + + assert_true(strlen(rnp_backend_string()) > 0 && strlen(rnp_backend_string()) < 255); + assert_true(strlen(rnp_backend_version()) > 0 && strlen(rnp_backend_version()) < 255); } static void @@ -5769,6 +5875,15 @@ assert_true(secret); assert_rnp_success(rnp_key_handle_destroy(key)); + /* import unprotected secret key with wrong crc */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_false( + import_sec_keys(ffi, "data/test_key_edge_cases/key-25519-tweaked-wrong-crc.asc")); + assert_rnp_success(rnp_get_public_key_count(ffi, &keycount)); + assert_int_equal(keycount, 0); + assert_rnp_success(rnp_get_secret_key_count(ffi, &keycount)); + assert_int_equal(keycount, 0); + /* cleanup */ rnp_ffi_destroy(ffi); } @@ -6101,6 +6216,9 @@ TEST_F(rnp_tests, test_ffi_calculate_iterations) { size_t iterations = 0; + assert_rnp_failure(rnp_calculate_iterations(NULL, 500, &iterations)); + assert_rnp_failure(rnp_calculate_iterations("SHA256", 500, NULL)); + assert_rnp_failure(rnp_calculate_iterations("WRONG", 500, &iterations)); assert_rnp_success(rnp_calculate_iterations("SHA256", 500, &iterations)); assert_true(iterations > 65536); } @@ -6146,9 +6264,16 @@ /* symmetric algorithms */ assert_rnp_success(rnp_supported_features("Symmetric Algorithm", &features)); assert_non_null(features); - assert_true(check_features(RNP_FEATURE_SYMM_ALG, features, 12)); + bool has_sm2 = sm2_enabled(); + bool has_tf = twofish_enabled(); + bool has_brainpool = brainpool_enabled(); + assert_true(check_features(RNP_FEATURE_SYMM_ALG, features, 10 + has_sm2 + has_tf)); rnp_buffer_destroy(features); bool supported = false; + assert_rnp_failure(rnp_supports_feature(NULL, "IDEA", &supported)); + assert_rnp_failure(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, NULL, &supported)); + assert_rnp_failure(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "IDEA", NULL)); + assert_rnp_failure(rnp_supports_feature("WRONG", "IDEA", &supported)); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "IDEA", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "TRIPLEDES", &supported)); @@ -6164,7 +6289,7 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "AES256", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "TWOFISH", &supported)); - assert_true(supported); + assert_true(supported == has_tf); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "CAMELLIA128", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "CAMELLIA192", &supported)); @@ -6172,7 +6297,7 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "CAMELLIA256", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "SM4", &supported)); - assert_true(supported); + assert_true(supported == has_sm2); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "idea", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "tripledes", &supported)); @@ -6188,7 +6313,7 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "aes256", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "twofish", &supported)); - assert_true(supported); + assert_true(supported == has_tf); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "camellia128", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "camellia192", &supported)); @@ -6196,17 +6321,21 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "camellia256", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "sm4", &supported)); - assert_true(supported); + assert_true(supported == has_sm2); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "wrong", &supported)); assert_false(supported); /* aead algorithms */ + bool has_eax = aead_eax_enabled(); + bool has_ocb = aead_ocb_enabled(); assert_rnp_success(rnp_supported_features(RNP_FEATURE_AEAD_ALG, &features)); assert_non_null(features); - assert_true(check_features(RNP_FEATURE_AEAD_ALG, features, 2)); + assert_true(check_features(RNP_FEATURE_AEAD_ALG, features, 1 + has_eax + has_ocb)); rnp_buffer_destroy(features); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "eax", &supported)); - assert_true(supported); + assert_true(supported == has_eax); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "ocb", &supported)); + assert_true(supported == has_ocb); + assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "none", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "wrong", &supported)); assert_false(supported); @@ -6222,7 +6351,7 @@ /* public key algorithm */ assert_rnp_success(rnp_supported_features(RNP_FEATURE_PK_ALG, &features)); assert_non_null(features); - assert_true(check_features(RNP_FEATURE_PK_ALG, features, 7)); + assert_true(check_features(RNP_FEATURE_PK_ALG, features, 6 + has_sm2)); rnp_buffer_destroy(features); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "RSA", &supported)); assert_true(supported); @@ -6237,7 +6366,7 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "EDDSA", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "SM2", &supported)); - assert_true(supported); + assert_true(supported == has_sm2); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "rsa", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "dsa", &supported)); @@ -6251,13 +6380,13 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "eddsa", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "sm2", &supported)); - assert_true(supported); + assert_true(supported == has_sm2); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_PK_ALG, "wrong", &supported)); assert_false(supported); /* hash algorithm */ assert_rnp_success(rnp_supported_features(RNP_FEATURE_HASH_ALG, &features)); assert_non_null(features); - assert_true(check_features(RNP_FEATURE_HASH_ALG, features, 10)); + assert_true(check_features(RNP_FEATURE_HASH_ALG, features, 9 + has_sm2)); rnp_buffer_destroy(features); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "MD5", &supported)); assert_true(supported); @@ -6278,7 +6407,7 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "SHA3-512", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "SM3", &supported)); - assert_true(supported); + assert_true(supported == has_sm2); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "md5", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "sha1", &supported)); @@ -6298,7 +6427,7 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "sha3-512", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "sm3", &supported)); - assert_true(supported); + assert_true(supported == has_sm2); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "wrong", &supported)); assert_false(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_HASH_ALG, "CRC24", &supported)); @@ -6321,7 +6450,7 @@ /* elliptic curve */ assert_rnp_success(rnp_supported_features(RNP_FEATURE_CURVE, &features)); assert_non_null(features); - assert_true(check_features(RNP_FEATURE_CURVE, features, 10)); + assert_true(check_features(RNP_FEATURE_CURVE, features, 6 + has_sm2 + 3 * has_brainpool)); rnp_buffer_destroy(features); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "NIST P-256", &supported)); assert_true(supported); @@ -6334,39 +6463,19 @@ assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "curve25519", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP256r1", &supported)); - assert_true(supported); + assert_true(supported == has_brainpool); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP384r1", &supported)); - assert_true(supported); + assert_true(supported == has_brainpool); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP512r1", &supported)); - assert_true(supported); + assert_true(supported == has_brainpool); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "secp256k1", &supported)); assert_true(supported); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "SM2 P-256", &supported)); - assert_true(supported); + assert_true(supported == has_sm2); assert_rnp_success(rnp_supports_feature(RNP_FEATURE_CURVE, "wrong", &supported)); assert_false(supported); } -TEST_F(rnp_tests, test_ffi_enable_debug) -{ - assert_rnp_success(rnp_enable_debug("dummy.c")); - assert_rnp_success(rnp_enable_debug("1.c")); - assert_true(rnp_get_debug("dummy.c")); - assert_true(rnp_get_debug("1.c")); - assert_false(rnp_get_debug("dummy")); - /* NULL enables debug for all sources */ - assert_rnp_success(rnp_enable_debug(NULL)); - assert_true(rnp_get_debug("anything")); - assert_rnp_success(rnp_disable_debug()); - assert_false(rnp_get_debug("anything")); - assert_false(rnp_get_debug("dummy.c")); - assert_false(rnp_get_debug("1.c")); - assert_rnp_success(rnp_enable_debug("all")); - assert_true(rnp_get_debug("anything other")); - /* need to clean it up afterwards - otherwise tests will go crazy */ - assert_rnp_success(rnp_disable_debug()); -} - TEST_F(rnp_tests, test_ffi_rnp_key_get_primary_grip) { rnp_ffi_t ffi = NULL; @@ -6737,7 +6846,15 @@ assert_rnp_failure(rnp_op_sign_set_hash(op, NULL)); assert_rnp_failure(rnp_op_sign_set_hash(op, "Unknown")); assert_rnp_success(rnp_op_sign_set_hash(op, "SHA256")); - // execute the operation + // execute the operation with wrong password + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "wrong")); + assert_int_equal(rnp_op_sign_execute(op), RNP_ERROR_BAD_PASSWORD); + assert_rnp_success(rnp_op_sign_destroy(op)); + // execute the operation with valid password + assert_rnp_success(rnp_op_sign_create(&op, ffi, input, output)); + // setup signature(s) + test_ffi_setup_signatures(&ffi, &op); assert_rnp_success(rnp_op_sign_execute(op)); // make sure the output file was created assert_rnp_success(rnp_output_memory_get_buf(output, &signed_buf, &signed_len, true)); @@ -6816,12 +6933,31 @@ // create encrypt operation assert_rnp_success(rnp_op_encrypt_create(&op, ffi, input, output)); // setup AEAD params - assert_rnp_success(rnp_op_encrypt_set_aead(op, "OCB")); + assert_rnp_failure(rnp_op_encrypt_set_aead(NULL, "OCB")); + assert_rnp_failure(rnp_op_encrypt_set_aead(op, NULL)); + assert_rnp_failure(rnp_op_encrypt_set_aead(op, "WRONG")); + if (!aead_ocb_enabled()) { + assert_rnp_failure(rnp_op_encrypt_set_aead(op, "OCB")); + } else { + assert_rnp_success(rnp_op_encrypt_set_aead(op, "OCB")); + } + assert_rnp_failure(rnp_op_encrypt_set_aead_bits(NULL, 10)); assert_rnp_failure(rnp_op_encrypt_set_aead_bits(op, -1)); assert_rnp_failure(rnp_op_encrypt_set_aead_bits(op, 60)); assert_rnp_success(rnp_op_encrypt_set_aead_bits(op, 10)); // add password (using all defaults) assert_rnp_success(rnp_op_encrypt_add_password(op, "pass1", NULL, 0, NULL)); + // setup compression + assert_rnp_failure(rnp_op_encrypt_set_compression(NULL, "ZLIB", 6)); + assert_rnp_failure(rnp_op_encrypt_set_compression(op, NULL, 6)); + assert_rnp_failure(rnp_op_encrypt_set_compression(op, "WRONG", 6)); + assert_rnp_success(rnp_op_encrypt_set_compression(op, "ZLIB", 6)); + // set filename and mtime + assert_rnp_failure(rnp_op_encrypt_set_file_name(NULL, "filename")); + assert_rnp_success(rnp_op_encrypt_set_file_name(op, NULL)); + assert_rnp_success(rnp_op_encrypt_set_file_name(op, "filename")); + assert_rnp_failure(rnp_op_encrypt_set_file_mtime(NULL, 1000)); + assert_rnp_success(rnp_op_encrypt_set_file_mtime(op, 1000)); // execute the operation assert_rnp_success(rnp_op_encrypt_execute(op)); // make sure the output file was created @@ -6848,14 +6984,24 @@ /* check the symmetric-key encrypted session key packet */ json_object *pkt = json_object_array_get_idx(jso, 0); assert_true(check_json_pkt_type(pkt, PGP_PKT_SK_SESSION_KEY)); - assert_true(check_json_field_int(pkt, "version", 5)); - assert_true(check_json_field_str(pkt, "aead algorithm.str", "OCB")); + if (!aead_ocb_enabled()) { + // if AEAD is not enabled then v4 encrypted packet will be created + assert_true(check_json_field_int(pkt, "version", 4)); + assert_true(check_json_field_str(pkt, "algorithm.str", "AES-256")); + } else { + assert_true(check_json_field_int(pkt, "version", 5)); + assert_true(check_json_field_str(pkt, "aead algorithm.str", "OCB")); + } /* check the aead-encrypted packet */ pkt = json_object_array_get_idx(jso, 1); - assert_true(check_json_pkt_type(pkt, PGP_PKT_AEAD_ENCRYPTED)); - assert_true(check_json_field_int(pkt, "version", 1)); - assert_true(check_json_field_str(pkt, "aead algorithm.str", "OCB")); - assert_true(check_json_field_int(pkt, "chunk size", 10)); + if (!aead_ocb_enabled()) { + assert_true(check_json_pkt_type(pkt, PGP_PKT_SE_IP_DATA)); + } else { + assert_true(check_json_pkt_type(pkt, PGP_PKT_AEAD_ENCRYPTED)); + assert_true(check_json_field_int(pkt, "version", 1)); + assert_true(check_json_field_str(pkt, "aead algorithm.str", "OCB")); + assert_true(check_json_field_int(pkt, "chunk size", 10)); + } json_object_put(jso); /* decrypt */ @@ -7155,7 +7301,11 @@ assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(verify)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(verify)); + } else { + assert_rnp_success(rnp_op_verify_execute(verify)); + } assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); assert_int_equal(sigcount, 0); rnp_op_verify_destroy(verify); @@ -7232,6 +7382,21 @@ rnp_input_destroy(input); rnp_output_destroy(output); + /* signed and password-encrypted data with 0 compression algo */ + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed-sym-none-z")); + assert_rnp_success(rnp_output_to_null(&output)); + verify = NULL; + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_success(rnp_op_verify_execute(verify)); + sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_SUCCESS)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + /* signed message with one-pass with wrong version */ assert_rnp_success( rnp_input_from_path(&input, "data/test_messages/message.txt.signed-no-z-malf")); @@ -7282,6 +7447,52 @@ rnp_input_destroy(input); rnp_output_destroy(output); + /* sha1 detached signature over the collision-suspicious data */ + /* allow sha1 temporary */ + rnp::SecurityRule allow_sha1( + rnp::FeatureType::Hash, PGP_HASH_SHA1, rnp::SecurityLevel::Default, 1547856001); + global_ctx.profile.add_rule(allow_sha1); + sigcount = 255; + assert_rnp_success(rnp_input_from_path(&source, "data/test_messages/shattered-1.pdf")); + assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/shattered-1.pdf.sig")); + assert_rnp_success(rnp_op_verify_detached_create(&verify, ffi, source, input)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_ERROR_SIGNATURE_INVALID)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(source); + rnp_input_destroy(input); + + /* sha1 detached signature over the document with collision*/ + sigcount = 255; + assert_rnp_success(rnp_input_from_path(&source, "data/test_messages/shattered-2.pdf")); + assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/shattered-1.pdf.sig")); + assert_rnp_success(rnp_op_verify_detached_create(&verify, ffi, source, input)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_ERROR_SIGNATURE_INVALID)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(source); + rnp_input_destroy(input); + + /* sha1 attached signature over the collision-suspicious data */ + sigcount = 255; + assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/shattered-2.pdf.gpg")); + assert_rnp_success(rnp_output_to_null(&output)); + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_ERROR_SIGNATURE_INVALID)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + + /* remove sha1 rule */ + assert_true(global_ctx.profile.del_rule(allow_sha1)); + /* signed message with key which is now expired */ assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); import_pub_keys(ffi, "data/test_messages/expired_signing_key-pub.asc"); @@ -7328,6 +7539,96 @@ rnp_input_destroy(input); rnp_output_destroy(output); + /* signed message with md5 hash */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(load_keys_gpg(ffi, "data/keyrings/1/pubring.gpg")); + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed.md5")); + assert_rnp_success(rnp_output_to_null(&output)); + verify = NULL; + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_ERROR_SIGNATURE_INVALID)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + + /* signed message with md5 hash before the cut-off date */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/key-rsa-2001-pub.asc")); + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed-md5-before")); + assert_rnp_success(rnp_output_to_null(&output)); + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_success(rnp_op_verify_execute(verify)); + sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_SUCCESS)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + + /* signed message with md5 hash right after the cut-off date */ + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed-md5-after")); + assert_rnp_success(rnp_output_to_null(&output)); + verify = NULL; + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_ERROR_SIGNATURE_INVALID)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + + /* signed message with sha1 hash */ + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed.sha1")); + assert_rnp_success(rnp_output_to_null(&output)); + verify = NULL; + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_ERROR_SIGNATURE_INVALID)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + + /* message signed with sha1 before the cut-off date */ + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed-sha1-before")); + assert_rnp_success(rnp_output_to_null(&output)); + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_success(rnp_op_verify_execute(verify)); + sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_SUCCESS)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + + /* message signed with sha1 right after the cut-off date */ + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed-sha1-after")); + assert_rnp_success(rnp_output_to_null(&output)); + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + assert_true(check_signature(verify, 0, RNP_ERROR_SIGNATURE_INVALID)); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + rnp_ffi_destroy(ffi); } @@ -7414,14 +7715,18 @@ rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-ocb")); assert_rnp_success(rnp_output_to_null(&output)); assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(verify)); + if (!aead_ocb_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(verify)); + } else { + assert_rnp_success(rnp_op_verify_execute(verify)); + } mode = NULL; cipher = NULL; valid = false; assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid)); assert_string_equal(mode, "aead-ocb"); assert_string_equal(cipher, "CAMELLIA192"); - assert_true(valid); + assert_true(valid == aead_ocb_enabled()); rnp_buffer_destroy(mode); rnp_buffer_destroy(cipher); rnp_op_verify_destroy(verify); @@ -7452,14 +7757,18 @@ rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-eax")); assert_rnp_success(rnp_output_to_null(&output)); assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(verify)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(verify)); + } else { + assert_rnp_success(rnp_op_verify_execute(verify)); + } mode = NULL; cipher = NULL; valid = false; assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid)); assert_string_equal(mode, "aead-eax"); assert_string_equal(cipher, "AES256"); - assert_true(valid); + assert_true(valid == aead_eax_enabled()); rnp_buffer_destroy(mode); rnp_buffer_destroy(cipher); rnp_op_verify_destroy(verify); @@ -7535,6 +7844,21 @@ rnp_op_verify_t verify = NULL; assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); assert_rnp_success(rnp_op_verify_execute(verify)); + /* check filename and mtime */ + char * filename = NULL; + uint32_t mtime = 0; + assert_rnp_failure(rnp_op_verify_get_file_info(NULL, &filename, &mtime)); + assert_rnp_success(rnp_op_verify_get_file_info(verify, &filename, &mtime)); + assert_string_equal(filename, "message.txt"); + assert_int_equal(mtime, 1571991574); + rnp_buffer_destroy(filename); + filename = NULL; + assert_rnp_success(rnp_op_verify_get_file_info(verify, &filename, NULL)); + assert_string_equal(filename, "message.txt"); + rnp_buffer_destroy(filename); + mtime = 0; + assert_rnp_success(rnp_op_verify_get_file_info(verify, NULL, &mtime)); + assert_int_equal(mtime, 1571991574); /* rnp_op_verify_get_recipient_count */ assert_rnp_failure(rnp_op_verify_get_recipient_count(verify, NULL)); size_t count = 255; @@ -7618,7 +7942,11 @@ rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-ocb")); assert_rnp_success(rnp_output_to_null(&output)); assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(verify)); + if (!aead_ocb_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(verify)); + } else { + assert_rnp_success(rnp_op_verify_execute(verify)); + } count = 255; assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count)); assert_int_equal(count, 0); @@ -7652,26 +7980,30 @@ assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations)); assert_int_equal(iterations, 30408704); assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc)); - assert_non_null(symenc); - cipher = NULL; - assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher)); - assert_string_equal(cipher, "CAMELLIA192"); - rnp_buffer_destroy(cipher); - aead = NULL; - assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead)); - assert_string_equal(aead, "OCB"); - rnp_buffer_destroy(aead); - hash = NULL; - assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash)); - assert_string_equal(hash, "SHA1"); - rnp_buffer_destroy(hash); - s2k = NULL; - assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k)); - assert_string_equal(s2k, "Iterated and salted"); - rnp_buffer_destroy(s2k); - iterations = 0; - assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations)); - assert_int_equal(iterations, 30408704); + if (!aead_ocb_enabled()) { + assert_null(symenc); + } else { + assert_non_null(symenc); + cipher = NULL; + assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher)); + assert_string_equal(cipher, "CAMELLIA192"); + rnp_buffer_destroy(cipher); + aead = NULL; + assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead)); + assert_string_equal(aead, "OCB"); + rnp_buffer_destroy(aead); + hash = NULL; + assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash)); + assert_string_equal(hash, "SHA1"); + rnp_buffer_destroy(hash); + s2k = NULL; + assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k)); + assert_string_equal(s2k, "Iterated and salted"); + rnp_buffer_destroy(s2k); + iterations = 0; + assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations)); + assert_int_equal(iterations, 30408704); + } rnp_op_verify_destroy(verify); rnp_input_destroy(input); rnp_output_destroy(output); @@ -7698,32 +8030,36 @@ rnp_buffer_destroy(keyid); recipient = NULL; assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient)); - assert_non_null(recipient); - assert_rnp_success(rnp_recipient_get_alg(recipient, &alg)); - assert_string_equal(alg, "RSA"); - rnp_buffer_destroy(alg); - assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid)); - assert_string_equal(keyid, "1ED63EE56FADC34D"); - rnp_buffer_destroy(keyid); - assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient)); - assert_non_null(recipient); - alg = NULL; - assert_rnp_success(rnp_recipient_get_alg(recipient, &alg)); - assert_string_equal(alg, "RSA"); - rnp_buffer_destroy(alg); - keyid = NULL; - assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid)); - assert_string_equal(keyid, "1ED63EE56FADC34D"); - rnp_buffer_destroy(keyid); - recipient = NULL; - assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient)); - assert_non_null(recipient); - assert_rnp_success(rnp_recipient_get_alg(recipient, &alg)); - assert_string_equal(alg, "RSA"); - rnp_buffer_destroy(alg); - assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid)); - assert_string_equal(keyid, "1ED63EE56FADC34D"); - rnp_buffer_destroy(keyid); + if (!aead_eax_enabled()) { + assert_null(recipient); + } else { + assert_non_null(recipient); + assert_rnp_success(rnp_recipient_get_alg(recipient, &alg)); + assert_string_equal(alg, "RSA"); + rnp_buffer_destroy(alg); + assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid)); + assert_string_equal(keyid, "1ED63EE56FADC34D"); + rnp_buffer_destroy(keyid); + assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient)); + assert_non_null(recipient); + alg = NULL; + assert_rnp_success(rnp_recipient_get_alg(recipient, &alg)); + assert_string_equal(alg, "RSA"); + rnp_buffer_destroy(alg); + keyid = NULL; + assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid)); + assert_string_equal(keyid, "1ED63EE56FADC34D"); + rnp_buffer_destroy(keyid); + recipient = NULL; + assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient)); + assert_non_null(recipient); + assert_rnp_success(rnp_recipient_get_alg(recipient, &alg)); + assert_string_equal(alg, "RSA"); + rnp_buffer_destroy(alg); + assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid)); + assert_string_equal(keyid, "1ED63EE56FADC34D"); + rnp_buffer_destroy(keyid); + } count = 255; assert_rnp_success(rnp_op_verify_get_symenc_count(verify, &count)); @@ -7761,7 +8097,11 @@ rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-eax")); assert_rnp_success(rnp_output_to_null(&output)); assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(verify)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(verify)); + } else { + assert_rnp_success(rnp_op_verify_execute(verify)); + } count = 255; assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count)); assert_int_equal(count, 1); @@ -7773,26 +8113,30 @@ assert_rnp_success(rnp_op_verify_get_symenc_at(verify, 0, &symenc)); assert_non_null(symenc); assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc)); - assert_non_null(symenc); - cipher = NULL; - assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher)); - assert_string_equal(cipher, "AES256"); - rnp_buffer_destroy(cipher); - aead = NULL; - assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead)); - assert_string_equal(aead, "EAX"); - rnp_buffer_destroy(aead); - hash = NULL; - assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash)); - assert_string_equal(hash, "SHA256"); - rnp_buffer_destroy(hash); - s2k = NULL; - assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k)); - assert_string_equal(s2k, "Iterated and salted"); - rnp_buffer_destroy(s2k); - iterations = 0; - assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations)); - assert_int_equal(iterations, 3932160); + if (!aead_eax_enabled()) { + assert_null(symenc); + } else { + assert_non_null(symenc); + cipher = NULL; + assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher)); + assert_string_equal(cipher, "AES256"); + rnp_buffer_destroy(cipher); + aead = NULL; + assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead)); + assert_string_equal(aead, "EAX"); + rnp_buffer_destroy(aead); + hash = NULL; + assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash)); + assert_string_equal(hash, "SHA256"); + rnp_buffer_destroy(hash); + s2k = NULL; + assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k)); + assert_string_equal(s2k, "Iterated and salted"); + rnp_buffer_destroy(s2k); + iterations = 0; + assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations)); + assert_int_equal(iterations, 3932160); + } rnp_op_verify_destroy(verify); rnp_input_destroy(input); rnp_output_destroy(output); @@ -8351,14 +8695,15 @@ assert_non_null(key); assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub)); assert_rnp_success(rnp_key_is_valid(key, &valid)); - /* key is not valid since function checks public key */ + /* key is not valid since expired */ assert_false(valid); assert_rnp_success(rnp_key_valid_till(key, &till)); assert_int_equal(till, 1577369391 + 16324055); assert_rnp_success(rnp_key_valid_till64(key, &till64)); assert_int_equal(till64, 1577369391 + 16324055); assert_false(key->pub->valid()); - assert_true(key->sec->valid()); + /* secret key part is also not valid till new sig is added */ + assert_false(key->sec->valid()); assert_rnp_success(rnp_key_is_valid(sub, &valid)); assert_false(valid); assert_rnp_success(rnp_key_valid_till(sub, &till)); @@ -8367,7 +8712,7 @@ assert_rnp_success(rnp_key_valid_till64(sub, &till64)); assert_int_equal(till64, 1577369391 + 16324055); assert_false(sub->pub->valid()); - assert_true(sub->sec->valid()); + assert_false(sub->sec->valid()); creation = 0; uint32_t validity = 2 * 30 * 24 * 60 * 60; // 2 monthes assert_rnp_success(rnp_key_get_creation(key, &creation)); @@ -8613,7 +8958,11 @@ assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); assert_rnp_success(rnp_op_verify_create(&op, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(op)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(op)); + } else { + assert_rnp_success(rnp_op_verify_execute(op)); + } rnp_op_verify_destroy(op); rnp_input_destroy(input); rnp_output_destroy(output); @@ -8625,7 +8974,11 @@ assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); assert_rnp_success(rnp_op_verify_create(&op, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(op)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(op)); + } else { + assert_rnp_success(rnp_op_verify_execute(op)); + } rnp_op_verify_destroy(op); rnp_input_destroy(input); rnp_output_destroy(output); @@ -8637,7 +8990,11 @@ assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); assert_rnp_success(rnp_op_verify_create(&op, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(op)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(op)); + } else { + assert_rnp_success(rnp_op_verify_execute(op)); + } rnp_op_verify_destroy(op); rnp_input_destroy(input); rnp_output_destroy(output); @@ -8649,7 +9006,11 @@ assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); assert_rnp_success(rnp_op_verify_create(&op, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(op)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(op)); + } else { + assert_rnp_success(rnp_op_verify_execute(op)); + } rnp_op_verify_destroy(op); rnp_input_destroy(input); rnp_output_destroy(output); @@ -8661,7 +9022,11 @@ assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); assert_rnp_success(rnp_op_verify_create(&op, ffi, input, output)); - assert_rnp_success(rnp_op_verify_execute(op)); + if (!aead_eax_enabled()) { + assert_rnp_failure(rnp_op_verify_execute(op)); + } else { + assert_rnp_success(rnp_op_verify_execute(op)); + } rnp_op_verify_destroy(op); rnp_input_destroy(input); rnp_output_destroy(output); @@ -10259,3 +10624,216 @@ rnp_ffi_destroy(ffi); } + +TEST_F(rnp_tests, test_ffi_set_log_fd) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_failure(rnp_ffi_set_log_fd(NULL, 0)); +#ifndef _WIN32 + /* on windows one below will terminate processing due to invalid parameters to fdopen() + * until we use _set_invalid_parameter_handler */ + assert_rnp_failure(rnp_ffi_set_log_fd(ffi, 100)); +#endif + int file_fd = rnp_open("tests.txt", O_RDWR | O_CREAT | O_TRUNC, 0777); + assert_true(file_fd > 0); + assert_rnp_success(rnp_ffi_set_log_fd(ffi, file_fd)); + rnp_input_t input = NULL; + const char *msg = "hello"; + assert_rnp_success( + rnp_input_from_memory(&input, (const uint8_t *) msg, strlen(msg), true)); + char *saved_env = NULL; + if (getenv(RNP_LOG_CONSOLE)) { + saved_env = strdup(getenv(RNP_LOG_CONSOLE)); + } + setenv(RNP_LOG_CONSOLE, "1", 1); + assert_rnp_failure(rnp_load_keys(ffi, "GPG", input, 119)); + assert_rnp_success(rnp_input_destroy(input)); + rnp_ffi_destroy(ffi); + if (saved_env) { + assert_int_equal(0, setenv(RNP_LOG_CONSOLE, saved_env, 1)); + free(saved_env); + } else { + unsetenv(RNP_LOG_CONSOLE); + } +#ifndef _WIN32 + assert_int_equal(fcntl(file_fd, F_GETFD), -1); + assert_int_equal(errno, EBADF); +#endif + char buffer[128] = {0}; + file_fd = rnp_open("tests.txt", O_RDONLY, 0); + int64_t rres = read(file_fd, buffer, sizeof(buffer)); + assert_true(rres > 0); + assert_non_null(strstr(buffer, "unexpected flags remaining: 0x")); + close(file_fd); +} + +TEST_F(rnp_tests, test_ffi_security_profile) +{ +#define MD5_FROM 1325376000 +#define SHA1_FROM 1547856000 + rnp_ffi_t ffi = NULL; + rnp_ffi_create(&ffi, "GPG", "GPG"); + /* check predefined rules */ + uint32_t flags = 0; + uint64_t from = 0; + uint32_t level = 0; + assert_rnp_failure( + rnp_get_security_rule(NULL, RNP_FEATURE_HASH_ALG, "SHA1", 0, &flags, &from, &level)); + assert_rnp_failure(rnp_get_security_rule(ffi, NULL, "SHA1", 0, &flags, &from, &level)); + assert_rnp_failure( + rnp_get_security_rule(ffi, RNP_FEATURE_SYMM_ALG, "AES256", 0, &flags, &from, &level)); + assert_rnp_failure( + rnp_get_security_rule(ffi, RNP_FEATURE_HASH_ALG, "Unknown", 0, &flags, &from, &level)); + assert_rnp_failure( + rnp_get_security_rule(ffi, RNP_FEATURE_HASH_ALG, "SHA1", 0, NULL, NULL, NULL)); + /* default rule */ + from = 256; + assert_rnp_success( + rnp_get_security_rule(ffi, RNP_FEATURE_HASH_ALG, "SHA256", 0, &flags, &from, &level)); + assert_int_equal(level, RNP_SECURITY_DEFAULT); + assert_int_equal(from, 0); + /* MD5 */ + from = 256; + assert_rnp_success( + rnp_get_security_rule(ffi, RNP_FEATURE_HASH_ALG, "MD5", 0, &flags, &from, &level)); + assert_int_equal(from, 0); + assert_int_equal(level, RNP_SECURITY_DEFAULT); + assert_rnp_success(rnp_get_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "MD5", time(NULL), &flags, &from, &level)); + assert_int_equal(from, MD5_FROM); + assert_int_equal(level, RNP_SECURITY_INSECURE); + assert_rnp_success(rnp_get_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "MD5", MD5_FROM - 1, &flags, &from, &level)); + assert_int_equal(from, 0); + assert_int_equal(flags, 0); + assert_int_equal(level, RNP_SECURITY_DEFAULT); + /* Override it */ + assert_rnp_failure(rnp_add_security_rule( + NULL, RNP_FEATURE_HASH_ALG, "MD5", RNP_SECURITY_OVERRIDE, 0, RNP_SECURITY_DEFAULT)); + assert_rnp_failure(rnp_add_security_rule( + ffi, RNP_FEATURE_SYMM_ALG, "MD5", RNP_SECURITY_OVERRIDE, 0, RNP_SECURITY_DEFAULT)); + assert_rnp_failure( + rnp_add_security_rule(ffi, NULL, "MD5", RNP_SECURITY_OVERRIDE, 0, RNP_SECURITY_DEFAULT)); + assert_rnp_failure(rnp_add_security_rule( + ffi, RNP_FEATURE_HASH_ALG, NULL, RNP_SECURITY_OVERRIDE, 0, RNP_SECURITY_DEFAULT)); + assert_rnp_failure(rnp_add_security_rule(ffi, + RNP_FEATURE_HASH_ALG, + "MD5", + RNP_SECURITY_OVERRIDE | 0x17, + 0, + RNP_SECURITY_DEFAULT)); + assert_rnp_failure( + rnp_add_security_rule(ffi, RNP_FEATURE_HASH_ALG, "MD5", RNP_SECURITY_OVERRIDE, 0, 25)); + assert_rnp_success(rnp_add_security_rule(ffi, + RNP_FEATURE_HASH_ALG, + "MD5", + RNP_SECURITY_OVERRIDE, + MD5_FROM - 1, + RNP_SECURITY_DEFAULT)); + assert_rnp_success(rnp_get_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "MD5", time(NULL), &flags, &from, &level)); + assert_int_equal(from, MD5_FROM - 1); + assert_int_equal(flags, RNP_SECURITY_OVERRIDE); + assert_int_equal(level, RNP_SECURITY_DEFAULT); + /* Remove and check back */ + size_t removed = 0; + assert_rnp_failure(rnp_remove_security_rule(NULL, + RNP_FEATURE_HASH_ALG, + "MD5", + RNP_SECURITY_DEFAULT, + RNP_SECURITY_OVERRIDE, + MD5_FROM - 1, + &removed)); + assert_rnp_failure(rnp_remove_security_rule(ffi, + RNP_FEATURE_SYMM_ALG, + "MD5", + RNP_SECURITY_DEFAULT, + RNP_SECURITY_OVERRIDE, + MD5_FROM - 1, + &removed)); + assert_rnp_success(rnp_remove_security_rule(ffi, + RNP_FEATURE_HASH_ALG, + "SHA256", + RNP_SECURITY_DEFAULT, + RNP_SECURITY_OVERRIDE, + MD5_FROM - 1, + &removed)); + assert_int_equal(removed, 0); + removed = 1; + assert_rnp_success(rnp_remove_security_rule(ffi, + RNP_FEATURE_HASH_ALG, + "MD5", + RNP_SECURITY_INSECURE, + RNP_SECURITY_OVERRIDE, + MD5_FROM - 1, + &removed)); + assert_int_equal(removed, 0); + removed = 1; + assert_rnp_success(rnp_remove_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "MD5", RNP_SECURITY_DEFAULT, 0, MD5_FROM - 1, &removed)); + assert_int_equal(removed, 0); + removed = 1; + assert_rnp_success(rnp_remove_security_rule(ffi, + RNP_FEATURE_HASH_ALG, + "MD5", + RNP_SECURITY_DEFAULT, + RNP_SECURITY_OVERRIDE, + MD5_FROM, + &removed)); + assert_int_equal(removed, 0); + assert_rnp_success(rnp_remove_security_rule(ffi, + RNP_FEATURE_HASH_ALG, + "MD5", + RNP_SECURITY_DEFAULT, + RNP_SECURITY_OVERRIDE, + MD5_FROM - 1, + &removed)); + assert_int_equal(removed, 1); + assert_rnp_success(rnp_get_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "MD5", time(NULL), &flags, &from, &level)); + assert_int_equal(from, 1325376000); + assert_int_equal(level, RNP_SECURITY_INSECURE); + assert_int_equal(flags, 0); + /* Remove all */ + removed = 0; + assert_rnp_failure(rnp_remove_security_rule(ffi, NULL, NULL, 0, 0x17, 0, &removed)); + assert_rnp_success(rnp_remove_security_rule(ffi, NULL, NULL, 0, 0, 0, &removed)); + assert_int_equal(removed, 2); + rnp_ffi_destroy(ffi); + rnp_ffi_create(&ffi, "GPG", "GPG"); + /* Remove all rules for hash */ + assert_rnp_failure( + rnp_remove_security_rule(ffi, RNP_FEATURE_SYMM_ALG, NULL, 0, 0, 0, &removed)); + removed = 0; + assert_rnp_success( + rnp_remove_security_rule(ffi, RNP_FEATURE_HASH_ALG, NULL, 0, 0, 0, &removed)); + assert_int_equal(removed, 2); + rnp_ffi_destroy(ffi); + rnp_ffi_create(&ffi, "GPG", "GPG"); + /* Remove all rules for specific hash */ + assert_rnp_success(rnp_remove_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "MD5", 0, RNP_SECURITY_REMOVE_ALL, 0, &removed)); + assert_int_equal(removed, 1); + assert_rnp_success(rnp_remove_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "SHA1", 0, RNP_SECURITY_REMOVE_ALL, 0, &removed)); + assert_int_equal(removed, 1); + rnp_ffi_destroy(ffi); + rnp_ffi_create(&ffi, "GPG", "GPG"); + /* SHA1 */ + from = 256; + assert_rnp_success( + rnp_get_security_rule(ffi, RNP_FEATURE_HASH_ALG, "SHA1", 0, &flags, &from, &level)); + assert_int_equal(from, 0); + assert_int_equal(level, RNP_SECURITY_DEFAULT); + assert_rnp_success(rnp_get_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "SHA1", time(NULL), &flags, &from, &level)); + assert_int_equal(from, SHA1_FROM); + assert_int_equal(level, RNP_SECURITY_INSECURE); + assert_rnp_success(rnp_get_security_rule( + ffi, RNP_FEATURE_HASH_ALG, "SHA1", SHA1_FROM - 1, &flags, &from, &level)); + assert_int_equal(from, 0); + assert_int_equal(level, RNP_SECURITY_DEFAULT); + + rnp_ffi_destroy(ffi); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi-enc.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi-enc.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi-enc.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi-enc.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -166,12 +166,38 @@ assert_rnp_success(rnp_output_to_path(&output, "encrypted")); assert_non_null(output); // create encrypt operation + assert_rnp_failure(rnp_op_encrypt_create(NULL, ffi, input, output)); + assert_rnp_failure(rnp_op_encrypt_create(&op, NULL, input, output)); + assert_rnp_failure(rnp_op_encrypt_create(&op, ffi, NULL, output)); + assert_rnp_failure(rnp_op_encrypt_create(&op, ffi, input, NULL)); assert_rnp_success(rnp_op_encrypt_create(&op, ffi, input, output)); // add password (using all defaults) + assert_rnp_failure(rnp_op_encrypt_add_password(NULL, "pass1", NULL, 0, NULL)); + assert_rnp_failure(rnp_op_encrypt_add_password(op, "", NULL, 0, NULL)); + assert_rnp_failure(rnp_op_encrypt_add_password(op, "pass1", "WRONG", 0, NULL)); + assert_rnp_failure(rnp_op_encrypt_add_password(op, "pass1", NULL, 0, "WRONG")); assert_rnp_success(rnp_op_encrypt_add_password(op, "pass1", NULL, 0, NULL)); // add password - assert_rnp_success(rnp_op_encrypt_add_password(op, "pass2", "SM3", 12345, "TWOFISH")); + if (!sm2_enabled() && !twofish_enabled()) { + assert_rnp_failure(rnp_op_encrypt_add_password(op, "pass2", "SM3", 12345, "TWOFISH")); + assert_rnp_failure( + rnp_op_encrypt_add_password(op, "pass2", "SHA256", 12345, "TWOFISH")); + assert_rnp_success( + rnp_op_encrypt_add_password(op, "pass2", "SHA256", 12345, "BLOWFISH")); + } else if (!sm2_enabled() && twofish_enabled()) { + assert_rnp_failure(rnp_op_encrypt_add_password(op, "pass2", "SM3", 12345, "TWOFISH")); + assert_rnp_success( + rnp_op_encrypt_add_password(op, "pass2", "SHA256", 12345, "TWOFISH")); + } else if (sm2_enabled() && !twofish_enabled()) { + assert_rnp_failure(rnp_op_encrypt_add_password(op, "pass2", "SM3", 12345, "TWOFISH")); + assert_rnp_success(rnp_op_encrypt_add_password(op, "pass2", "SM3", 12345, "BLOWFISH")); + } else { + assert_rnp_success(rnp_op_encrypt_add_password(op, "pass2", "SM3", 12345, "TWOFISH")); + } // set the data encryption cipher + assert_rnp_failure(rnp_op_encrypt_set_cipher(NULL, "CAST5")); + assert_rnp_failure(rnp_op_encrypt_set_cipher(op, NULL)); + assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "WRONG")); assert_rnp_success(rnp_op_encrypt_set_cipher(op, "CAST5")); // execute the operation assert_rnp_success(rnp_op_encrypt_execute(op)); @@ -221,8 +247,7 @@ assert_non_null(input); assert_rnp_success(rnp_output_to_path(&output, "decrypted")); assert_non_null(output); - assert_int_equal( - RNP_SUCCESS, + assert_rnp_success( rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "pass1")); assert_rnp_success(rnp_decrypt(ffi, input, output)); // cleanup @@ -281,7 +306,19 @@ assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb_inc, &pswdnum)); assert_rnp_success(rnp_op_encrypt_add_password(op, NULL, NULL, 0, NULL)); // add another password with different encryption parameters - assert_rnp_success(rnp_op_encrypt_add_password(op, NULL, "SM3", 12345, "TWOFISH")); + if (!sm2_enabled() && !twofish_enabled()) { + assert_rnp_failure(rnp_op_encrypt_add_password(op, NULL, "SM3", 12345, "TWOFISH")); + assert_rnp_failure(rnp_op_encrypt_add_password(op, NULL, "SHA256", 12345, "TWOFISH")); + assert_rnp_success(rnp_op_encrypt_add_password(op, NULL, "SHA256", 12345, "BLOWFISH")); + } else if (!sm2_enabled() && twofish_enabled()) { + assert_rnp_failure(rnp_op_encrypt_add_password(op, NULL, "SM3", 12345, "TWOFISH")); + assert_rnp_success(rnp_op_encrypt_add_password(op, NULL, "SHA256", 12345, "TWOFISH")); + } else if (sm2_enabled() && !twofish_enabled()) { + assert_rnp_failure(rnp_op_encrypt_add_password(op, NULL, "SM3", 12345, "TWOFISH")); + assert_rnp_success(rnp_op_encrypt_add_password(op, NULL, "SM3", 12345, "BLOWFISH")); + } else { + assert_rnp_success(rnp_op_encrypt_add_password(op, NULL, "SM3", 12345, "TWOFISH")); + } // set the data encryption cipher assert_rnp_success(rnp_op_encrypt_set_cipher(op, "CAMELLIA256")); // execute the operation @@ -355,6 +392,8 @@ // add recipients rnp_key_handle_t key = NULL; assert_rnp_success(rnp_locate_key(ffi, "userid", "key0-uid2", &key)); + assert_rnp_failure(rnp_op_encrypt_add_recipient(NULL, key)); + assert_rnp_failure(rnp_op_encrypt_add_recipient(op, NULL)); assert_rnp_success(rnp_op_encrypt_add_recipient(op, key)); rnp_key_handle_destroy(key); key = NULL; @@ -594,12 +633,20 @@ // set the data encryption cipher assert_rnp_success(rnp_op_encrypt_set_cipher(op, "CAST5")); // enable armoring + assert_rnp_failure(rnp_op_encrypt_set_armor(NULL, true)); assert_rnp_success(rnp_op_encrypt_set_armor(op, true)); // add signature + assert_rnp_failure(rnp_op_encrypt_set_hash(NULL, "SHA256")); + assert_rnp_failure(rnp_op_encrypt_set_hash(op, NULL)); + assert_rnp_failure(rnp_op_encrypt_set_hash(op, "WRONG")); assert_rnp_success(rnp_op_encrypt_set_hash(op, "SHA1")); + assert_rnp_failure(rnp_op_encrypt_set_creation_time(NULL, 0)); assert_rnp_success(rnp_op_encrypt_set_creation_time(op, 0)); + assert_rnp_failure(rnp_op_encrypt_set_expiration_time(NULL, 0)); assert_rnp_success(rnp_op_encrypt_set_expiration_time(op, 0)); assert_rnp_success(rnp_locate_key(ffi, "userid", "key1-uid1", &key)); + assert_rnp_failure(rnp_op_encrypt_add_signature(NULL, key, NULL)); + assert_rnp_failure(rnp_op_encrypt_add_signature(op, NULL, NULL)); assert_rnp_success(rnp_op_encrypt_add_signature(op, key, NULL)); rnp_key_handle_destroy(key); key = NULL; @@ -856,3 +903,67 @@ rnp_ffi_destroy(ffi); } + +TEST_F(rnp_tests, test_ffi_decrypt_small_rsa) +{ + rnp_ffi_t ffi = NULL; + const char *plaintext = "data1"; + + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_all_keys(ffi, "data/test_key_validity/rsa_key_small_sig-sec.asc")); + rnp_input_t input = NULL; + assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/data.enc.small-rsa")); + rnp_output_t output = NULL; + assert_rnp_success(rnp_output_to_memory(&output, 0)); + assert_rnp_success(rnp_decrypt(ffi, input, output)); + size_t len = 0; + uint8_t *buf = NULL; + assert_rnp_success(rnp_output_memory_get_buf(output, &buf, &len, false)); + assert_int_equal(len, 5); + assert_int_equal(memcmp(plaintext, buf, 5), 0); + assert_rnp_success(rnp_input_destroy(input)); + assert_rnp_success(rnp_output_destroy(output)); + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_decrypt_small_eg) +{ + /* make sure unlock and decrypt fails with invalid key */ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/key-eg-small-subgroup-sec.pgp")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "3b8dda452b9f69b4", &key)); + assert_non_null(key); + /* key is not encrypted */ + assert_rnp_success(rnp_key_unlock(key, NULL)); + rnp_key_handle_destroy(key); + rnp_input_t input = NULL; + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.enc-eg-bad")); + rnp_output_t output = NULL; + assert_rnp_success(rnp_output_to_null(&output)); + assert_rnp_failure(rnp_decrypt(ffi, input, output)); + assert_rnp_success(rnp_input_destroy(input)); + assert_rnp_success(rnp_output_destroy(output)); + rnp_ffi_destroy(ffi); + /* make sure unlock and decrypt fails with invalid encrypted key */ + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/key-eg-small-subgroup-sec-enc.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "3b072c3bb2d1a8b2", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_unlock(key, "password")); + assert_rnp_success(rnp_key_lock(key)); + rnp_key_handle_destroy(key); + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.enc-eg-bad2")); + assert_rnp_success(rnp_output_to_null(&output)); + assert_rnp_failure(rnp_decrypt(ffi, input, output)); + assert_rnp_success(rnp_input_destroy(input)); + assert_rnp_success(rnp_output_destroy(output)); + rnp_ffi_destroy(ffi); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi-key-prop.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi-key-prop.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi-key-prop.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi-key-prop.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -29,32 +29,6 @@ #include "rnp_tests.h" #include "support.h" -static bool -check_uid_valid(rnp_key_handle_t key, size_t idx, bool valid) -{ - rnp_uid_handle_t uid = NULL; - if (rnp_key_get_uid_handle_at(key, idx, &uid)) { - return false; - } - bool val = !valid; - rnp_uid_is_valid(uid, &val); - rnp_uid_handle_destroy(uid); - return val == valid; -} - -static bool -check_uid_primary(rnp_key_handle_t key, size_t idx, bool primary) -{ - rnp_uid_handle_t uid = NULL; - if (rnp_key_get_uid_handle_at(key, idx, &uid)) { - return false; - } - bool prim = !primary; - rnp_uid_is_primary(uid, &prim); - rnp_uid_handle_destroy(uid); - return prim == primary; -} - TEST_F(rnp_tests, test_ffi_key_set_expiry_multiple_uids) { rnp_ffi_t ffi = NULL; @@ -159,3 +133,149 @@ rnp_ffi_destroy(ffi); } + +TEST_F(rnp_tests, test_ffi_key_primary_uid_conflict) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + + /* load key with 1 uid and two certifications: first marks uid primary, but expires key + * second marks uid as non-primary, but has zero key expiration */ + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/key-primary-uid-conflict-pub.pgp")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "userid", "userid_2_sigs", &key)); + assert_int_equal(get_key_uids(key), 1); + assert_int_equal(get_key_expiry(key), 0); + assert_true(check_key_valid(key, true)); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_primary(key, 0, false)); + rnp_key_handle_destroy(key); + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_expired_certification_and_direct_sig) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + + /* load key with 2 uids and direct-key signature: + * - direct-key sig has 0 key expiration time but expires in 30 seconds + * - first uid is not primary, but key expiration is 60 seconds + * - second uid is marked as primary, doesn't expire key, but certification expires in 60 + * seconds */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/key-expired-cert-direct.pgp")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "userid", "primary-uid-expired-cert", &key)); + assert_null(key); + assert_rnp_success(rnp_locate_key(ffi, "userid", "expired-certifications", &key)); + assert_non_null(key); + assert_int_equal(get_key_uids(key), 2); + assert_int_equal(get_key_expiry(key), 60); + rnp_signature_handle_t sig = NULL; + assert_rnp_success(rnp_key_get_signature_at(key, 0, &sig)); + assert_non_null(sig); + assert_int_equal(rnp_signature_is_valid(sig, 0), RNP_ERROR_SIGNATURE_EXPIRED); + rnp_signature_handle_destroy(sig); + assert_true(check_key_valid(key, false)); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_primary(key, 0, false)); + assert_true(check_uid_valid(key, 1, false)); + assert_true(check_uid_primary(key, 1, false)); + rnp_key_handle_destroy(key); + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_25519_tweaked_bits) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + /* try public key */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/key-25519-non-tweaked.asc")); + rnp_key_handle_t sub = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + bool tweaked = true; + assert_rnp_failure(rnp_key_25519_bits_tweaked(NULL, &tweaked)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, NULL)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_rnp_failure(rnp_key_25519_bits_tweak(NULL)); + assert_rnp_failure(rnp_key_25519_bits_tweak(sub)); + rnp_key_handle_destroy(sub); + /* load secret key */ + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/key-25519-non-tweaked-sec.asc")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(NULL, &tweaked)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, NULL)); + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_false(tweaked); + /* protect key and try again */ + assert_rnp_success(rnp_key_protect(sub, "password", NULL, NULL, NULL, 100000)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_rnp_success(rnp_key_unlock(sub, "password")); + tweaked = true; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_false(tweaked); + assert_rnp_success(rnp_key_lock(sub)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, &tweaked)); + /* now let's tweak it */ + assert_rnp_failure(rnp_key_25519_bits_tweak(NULL)); + assert_rnp_failure(rnp_key_25519_bits_tweak(sub)); + assert_rnp_success(rnp_key_unlock(sub, "password")); + assert_rnp_failure(rnp_key_25519_bits_tweak(sub)); + assert_rnp_success(rnp_key_unprotect(sub, "password")); + assert_rnp_success(rnp_key_25519_bits_tweak(sub)); + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + /* export unprotected key */ + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "3176FC1486AA2528", &key)); + auto clearsecdata = export_key(key, true, true); + rnp_key_handle_destroy(key); + assert_rnp_success(rnp_key_protect(sub, "password", NULL, NULL, NULL, 100000)); + rnp_key_handle_destroy(sub); + /* make sure it is exported and saved tweaked and protected */ + assert_rnp_success(rnp_locate_key(ffi, "keyid", "3176FC1486AA2528", &key)); + auto secdata = export_key(key, true, true); + rnp_key_handle_destroy(key); + reload_keyrings(&ffi); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + bool prot = false; + assert_rnp_success(rnp_key_is_protected(sub, &prot)); + assert_true(prot); + assert_rnp_success(rnp_key_unlock(sub, "password")); + tweaked = false; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + rnp_key_handle_destroy(sub); + rnp_ffi_destroy(ffi); + /* import cleartext exported key */ + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_all_keys(ffi, clearsecdata.data(), clearsecdata.size())); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + prot = true; + assert_rnp_success(rnp_key_is_protected(sub, &prot)); + assert_false(prot); + tweaked = false; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + rnp_key_handle_destroy(sub); + rnp_ffi_destroy(ffi); + /* import exported key */ + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_all_keys(ffi, secdata.data(), secdata.size())); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + prot = false; + assert_rnp_success(rnp_key_is_protected(sub, &prot)); + assert_true(prot); + assert_rnp_success(rnp_key_unlock(sub, "password")); + tweaked = false; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + rnp_key_handle_destroy(sub); + rnp_ffi_destroy(ffi); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi-key-sig.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi-key-sig.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/ffi-key-sig.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/ffi-key-sig.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -771,6 +771,9 @@ assert_string_equal(sigtype, "certification (generic)"); rnp_buffer_destroy(sigtype); assert_int_equal(rnp_signature_is_valid(sig, 0), RNP_ERROR_SIGNATURE_EXPIRED); + uint32_t expires = 0; + assert_rnp_success(rnp_signature_get_expiration(sig, &expires)); + assert_int_equal(expires, 86400); rnp_signature_handle_destroy(sig); rnp_uid_handle_destroy(uid); rnp_key_handle_destroy(key); @@ -1392,3 +1395,104 @@ rnp_key_handle_destroy(key); assert_rnp_success(rnp_ffi_destroy(ffi)); } + +TEST_F(rnp_tests, test_ffi_rsa_small_sig) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_pub_keys(ffi, "data/test_key_validity/rsa_key_small_sig-pub.asc")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "ED23B0105947F283", &key)); + rnp_uid_handle_t uid = NULL; + assert_rnp_success(rnp_key_get_uid_handle_at(key, 0, &uid)); + bool valid = false; + assert_rnp_success(rnp_uid_is_valid(uid, &valid)); + assert_true(valid); + rnp_uid_handle_destroy(uid); + rnp_key_handle_destroy(key); + assert_rnp_success(rnp_ffi_destroy(ffi)); +} + +TEST_F(rnp_tests, test_ffi_key_critical_notations) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + + /* Load key with 2 unknown critical notations in certification */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/key-critical-notations.pgp")); + rnp_key_handle_t key = NULL; + /* key is valid since it has valid subkey binding, but userid is not valid */ + assert_rnp_success(rnp_locate_key(ffi, "userid", "critical-key", &key)); + assert_null(key); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "ddc610bb7b8f689c", &key)); + assert_non_null(key); + assert_true(check_key_valid(key, true)); + /* uid is not valid, as certification has unknown critical notation */ + assert_true(check_uid_valid(key, 0, false)); + assert_true(check_sub_valid(key, 0, true)); + rnp_key_handle_destroy(key); + rnp_ffi_destroy(ffi); + + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + /* Load key with unknown critical notations in both certification and binding */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/key-sub-crit-note-pub.pgp")); + /* key is not valid, as well as sub and uid */ + assert_rnp_success(rnp_locate_key(ffi, "userid", "critical_notation", &key)); + assert_null(key); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "9988c1bcb55391d6", &key)); + assert_non_null(key); + assert_true(check_key_valid(key, false)); + assert_true(check_uid_valid(key, 0, false)); + assert_true(check_sub_valid(key, 0, false)); + rnp_key_handle_destroy(key); + rnp_ffi_destroy(ffi); + + /* Verify data signature with unknown critical notation */ + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(load_keys_gpg(ffi, "data/keyrings/1/pubring.gpg")); + rnp_input_t input = NULL; + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed.crit-notation")); + rnp_output_t output = NULL; + assert_rnp_success(rnp_output_to_null(&output)); + rnp_op_verify_t verify = NULL; + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_failure(rnp_op_verify_execute(verify)); + size_t sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + rnp_op_verify_signature_t sig = NULL; + assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig)); + assert_int_equal(rnp_op_verify_signature_get_status(sig), RNP_ERROR_SIGNATURE_INVALID); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_import_invalid_issuer) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + + /* public key + secret subkey with invalid signer's keyfp */ + rnp_input_t input = NULL; + assert_rnp_success( + rnp_input_from_path(&input, "data/test_key_edge_cases/alice-sub-sig-fp.pgp")); + char * keys = NULL; + uint32_t flags = + RNP_LOAD_SAVE_PUBLIC_KEYS | RNP_LOAD_SAVE_SECRET_KEYS | RNP_LOAD_SAVE_SINGLE; + assert_rnp_success(rnp_import_keys(ffi, input, flags, &keys)); + rnp_input_destroy(input); + rnp_buffer_destroy(keys); + + /* public key + secret subkey with invalid signer's keyid */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_rnp_success( + rnp_input_from_path(&input, "data/test_key_edge_cases/alice-sub-sig-keyid.pgp")); + assert_rnp_success(rnp_import_keys(ffi, input, flags, &keys)); + rnp_input_destroy(input); + rnp_buffer_destroy(keys); + + rnp_ffi_destroy(ffi); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_dump.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_dump.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_dump.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_dump.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -39,4 +39,9 @@ time_t start = time(NULL); assert_int_equal(dump_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); assert_true(time(NULL) - start <= 1800); + + data = file_to_vec(DATA_PATH "timeout-7e498daecad7ee646371a466d4a317c59fe7db89"); + start = time(NULL); + assert_int_equal(dump_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); + assert_true(time(NULL) - start <= 30); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_keyimport.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_keyimport.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_keyimport.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_keyimport.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -48,4 +48,7 @@ data = file_to_vec(DATA_PATH "timeout_9c10372fe9ebdcdb0b6e275d05f8af4f4e3d6051"); assert_int_equal(keyimport_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); + + data = file_to_vec(DATA_PATH "leak_371b211d7e9cf9857befcf06c7da74835e249ee7"); + assert_int_equal(keyimport_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_keyring_kbx.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_keyring_kbx.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_keyring_kbx.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_keyring_kbx.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -45,4 +45,8 @@ /* Issue 25388 in oss-fuzz: rnp:fuzz_keyring_kbx: Heap-buffer-overflow in mem_src_read */ data = file_to_vec(DATA_PATH "crash-b894a2f79f7d38a16ae0ee8d74972336aa3f5798"); assert_int_equal(keyring_kbx_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); + + /* Leak found during CI run */ + data = file_to_vec(DATA_PATH "leak-b02cd1c6b70c10a8a673a34ba3770b39468b7ddf"); + assert_int_equal(keyring_kbx_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_sigimport.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_sigimport.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_sigimport.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_sigimport.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "rnp_tests.h" +#include "support.h" + +extern "C" int sigimport_LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +#define DATA_PATH "data/test_fuzz_sigimport/" + +TEST_F(rnp_tests, test_fuzz_sigimport) +{ + /* issue 39578 in oss-fuzz: timeout */ + auto data = file_to_vec(DATA_PATH "timeout-821848a7b6b667fc41e5ff130415b3efd22ed118"); + assert_int_equal(sigimport_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_verify.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_verify.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_verify.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_verify.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "rnp_tests.h" +#include "support.h" +#include + +extern "C" int verify_LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +#define DATA_PATH "data/test_fuzz_verify/" + +TEST_F(rnp_tests, test_fuzz_verify) +{ + auto data = file_to_vec(DATA_PATH "timeout-25b8c9d824c8eb492c827689795748298a2b0a46"); + assert_int_equal(verify_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); + + data = file_to_vec(DATA_PATH "timeout-c2aff538c73b447bca689005e9762840b5a022d0"); + assert_int_equal(verify_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_verify_detached.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_verify_detached.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/fuzz_verify_detached.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/fuzz_verify_detached.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -41,4 +41,7 @@ data = file_to_vec(DATA_PATH "outofmemory-23094cb781b2cf6d1749ebac8bd0576e51440498-z"); assert_int_equal(verify_detached_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); + + data = file_to_vec(DATA_PATH "outofmemory-dea88a4aa4ab5fec1291446db702ee893d5559cf"); + assert_int_equal(verify_detached_LLVMFuzzerTestOneInput(data.data(), data.size()), 0); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/generatekey.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/generatekey.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/generatekey.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/generatekey.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -40,8 +40,6 @@ #include "defaults.h" #include -extern rng_t global_rng; - static bool generate_test_key(const char *keystore, const char *userid, const char *hash, const char *home) { @@ -57,12 +55,12 @@ std::vector keys; /* Generate the key */ - cli_set_default_rsa_key_desc(cli_rnp_cfg(rnp), hash); + cli_set_default_rsa_key_desc(rnp.cfg(), hash); if (!cli_rnp_generate_key(&rnp, userid)) { goto done; } - if (!cli_rnp_load_keyrings(&rnp, true)) { + if (!rnp.load_keyrings(true)) { goto done; } if (rnp_get_public_key_count(rnp.ffi, &keycount) || (keycount != 2)) { @@ -84,10 +82,25 @@ close(pipefd[0]); } clear_key_handles(keys); - cli_rnp_end(&rnp); + rnp.end(); return res; } +static bool +hash_supported(const std::string &hash) +{ + if (!sm2_enabled() && lowercase(hash) == "sm3") { + return false; + } + return true; +} + +static bool +hash_secure(const std::string &hash) +{ + return (lowercase(hash) != "md5") && (lowercase(hash) != "sha1"); +} + TEST_F(rnp_tests, rnpkeys_generatekey_testSignature) { /* Set the UserId = custom value. @@ -132,13 +145,13 @@ /* Setup password input and rnp structure */ assert_true(setup_cli_rnp_common(&rnp, RNP_KEYSTORE_GPG, NULL, pipefd)); /* Load keyring */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); size_t seccount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &seccount)); assert_true(seccount > 0); /* Setup signing context */ - rnp_cfg &cfg = cli_rnp_cfg(rnp); + rnp_cfg &cfg = rnp.cfg(); cfg.load_defaults(); cfg.set_bool(CFG_ARMOR, armored); cfg.set_bool(CFG_SIGN_NEEDED, true); @@ -150,6 +163,12 @@ cfg.add_str(CFG_SIGNERS, userId); /* Sign the file */ + if (!hash_supported(hashAlg[i])) { + assert_false(cli_rnp_protect_file(&rnp)); + rnp.end(); + assert_int_equal(rnp_unlink("dummyfile.dat.pgp"), -1); + continue; + } assert_true(cli_rnp_protect_file(&rnp)); if (pipefd[0] != -1) { close(pipefd[0]); @@ -162,6 +181,12 @@ cfg.set_bool(CFG_OVERWRITE, true); cfg.set_str(CFG_INFILE, "dummyfile.dat.pgp"); cfg.set_str(CFG_OUTFILE, "dummyfile.verify"); + if (!hash_secure(hashAlg[i])) { + assert_false(cli_rnp_process_file(&rnp)); + rnp.end(); + assert_int_equal(rnp_unlink("dummyfile.dat.pgp"), 0); + continue; + } assert_true(cli_rnp_process_file(&rnp)); /* Ensure signature verification passed */ @@ -187,7 +212,7 @@ assert_false(cli_rnp_process_file(&rnp)); } - cli_rnp_end(&rnp); + rnp.end(); assert_int_equal(rnp_unlink("dummyfile.dat.pgp"), 0); rnp_unlink("dummyfile.verify"); } @@ -196,13 +221,25 @@ assert_int_equal(rnp_unlink("dummyfile.dat"), 0); } +static bool +cipher_supported(const std::string &cipher) +{ + if (!sm2_enabled() && lowercase(cipher) == "sm4") { + return false; + } + if (!twofish_enabled() && lowercase(cipher) == "twofish") { + return false; + } + return true; +} + TEST_F(rnp_tests, rnpkeys_generatekey_testEncryption) { const char *cipherAlg[] = { - "BLOWFISH", "TWOFISH", "CAST5", "TRIPLEDES", "AES128", "AES192", - "AES256", "CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "blowfish", "twofish", - "cast5", "tripledes", "aes128", "aes192", "aes256", "camellia128", - "camellia192", "camellia256", NULL}; + "BLOWFISH", "TWOFISH", "CAST5", "TRIPLEDES", "AES128", "AES192", + "AES256", "CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "SM4", "blowfish", + "twofish", "cast5", "tripledes", "aes128", "aes192", "aes256", + "camellia128", "camellia192", "camellia256", "sm4", NULL}; cli_rnp_t rnp = {}; char memToEncrypt[] = "A simple test message"; @@ -219,12 +256,12 @@ /* Set up rnp and encrypt the dataa */ assert_true(setup_cli_rnp_common(&rnp, RNP_KEYSTORE_GPG, NULL, NULL)); /* Load keyring */ - assert_true(cli_rnp_load_keyrings(&rnp, false)); + assert_true(rnp.load_keyrings(false)); size_t seccount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &seccount)); assert_true(seccount == 0); /* Set the cipher and armored flags */ - rnp_cfg &cfg = cli_rnp_cfg(rnp); + rnp_cfg &cfg = rnp.cfg(); cfg.load_defaults(); cfg.set_bool(CFG_ARMOR, armored); cfg.set_bool(CFG_ENCRYPT_PK, true); @@ -234,23 +271,27 @@ cfg.set_str(CFG_CIPHER, cipherAlg[i]); cfg.add_str(CFG_RECIPIENTS, userid); /* Encrypt the file */ - assert_true(cli_rnp_protect_file(&rnp)); - cli_rnp_end(&rnp); + bool supported = cipher_supported(cipherAlg[i]); + assert_true(cli_rnp_protect_file(&rnp) == supported); + rnp.end(); + if (!supported) { + continue; + } /* Set up rnp again and decrypt the file */ assert_true(setup_cli_rnp_common(&rnp, RNP_KEYSTORE_GPG, NULL, pipefd)); /* Load the keyrings */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &seccount)); assert_true(seccount > 0); /* Setup the decryption context and decrypt */ - rnp_cfg &newcfg = cli_rnp_cfg(rnp); + rnp_cfg &newcfg = rnp.cfg(); newcfg.load_defaults(); newcfg.set_bool(CFG_OVERWRITE, true); newcfg.set_str(CFG_INFILE, "dummyfile.dat.pgp"); newcfg.set_str(CFG_OUTFILE, "dummyfile.decrypt"); assert_true(cli_rnp_process_file(&rnp)); - cli_rnp_end(&rnp); + rnp.end(); if (pipefd[0] != -1) { close(pipefd[0]); } @@ -290,13 +331,17 @@ for (size_t i = 0; i < ARRAY_SIZE(hashAlg); i++) { const char *keystore = keystores[i % ARRAY_SIZE(keystores)]; /* Setting up rnp again and decrypting memory */ - printf("keystore: %s\n", keystore); + printf("keystore: %s, hashalg %s\n", keystore, hashAlg[i]); /* Generate key with specified hash algorithm */ - assert_true(generate_test_key(keystore, hashAlg[i], hashAlg[i], NULL)); + bool supported = hash_supported(hashAlg[i]); + assert_true(generate_test_key(keystore, hashAlg[i], hashAlg[i], NULL) == supported); + if (!supported) { + continue; + } /* Load and check key */ assert_true(setup_cli_rnp_common(&rnp, keystore, NULL, NULL)); /* Loading the keyrings */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); /* Some minor checks */ size_t keycount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &keycount)); @@ -306,9 +351,16 @@ assert_true(keycount > 0); rnp_key_handle_t handle = NULL; assert_rnp_success(rnp_locate_key(rnp.ffi, "userid", hashAlg[i], &handle)); - assert_non_null(handle); + if (hash_secure(hashAlg[i])) { + assert_non_null(handle); + bool valid = false; + rnp_key_is_valid(handle, &valid); + assert_true(valid); + } else { + assert_null(handle); + } rnp_key_handle_destroy(handle); - cli_rnp_end(&rnp); + rnp.end(); delete_recursively(".rnp"); } } @@ -338,7 +390,7 @@ /* Initialize the basic RNP structure. */ assert_true(setup_cli_rnp_common(&rnp, keystore, NULL, NULL)); /* Load the newly generated rnp key*/ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); size_t keycount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &keycount)); assert_true(keycount > 0); @@ -350,7 +402,7 @@ assert_rnp_success(rnp_locate_key(rnp.ffi, "userid", userIds[i], &handle)); assert_non_null(handle); rnp_key_handle_destroy(handle); - cli_rnp_end(&rnp); + rnp.end(); delete_recursively(".rnp"); } } @@ -375,7 +427,7 @@ assert_true(path_rnp_file_exists(".rnp/secring.gpg", NULL)); /* Loading keyrings and checking whether they have correct key */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); size_t keycount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &keycount)); assert_int_equal(keycount, 2); @@ -389,7 +441,7 @@ assert_rnp_success(rnp_locate_key(rnp.ffi, "userid", userid.c_str(), &handle)); assert_non_null(handle); rnp_key_handle_destroy(handle); - cli_rnp_end(&rnp); + rnp.end(); /* Now we start over with a new home. When home is specified explicitly then it should * include .rnp as well */ @@ -412,7 +464,7 @@ assert_true(path_rnp_file_exists(newhome.c_str(), "secring.gpg", NULL)); /* Loading keyrings and checking whether they have correct key */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); keycount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &keycount)); assert_int_equal(keycount, 2); @@ -426,7 +478,7 @@ assert_rnp_success(rnp_locate_key(rnp.ffi, "userid", "newhomekey", &handle)); assert_non_null(handle); rnp_key_handle_destroy(handle); - cli_rnp_end(&rnp); // Free memory and other allocated resources. + rnp.end(); // Free memory and other allocated resources. } TEST_F(rnp_tests, rnpkeys_generatekey_verifykeyKBXHomeDirOption) @@ -451,7 +503,7 @@ assert_false(path_rnp_file_exists(".rnp/secring.gpg", NULL)); /* Loading keyrings and checking whether they have correct key */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); size_t keycount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &keycount)); assert_int_equal(keycount, 2); @@ -464,7 +516,7 @@ assert_rnp_success(rnp_locate_key(rnp.ffi, "userid", userid.c_str(), &handle)); assert_non_null(handle); rnp_key_handle_destroy(handle); - cli_rnp_end(&rnp); + rnp.end(); /* Now we start over with a new home. */ path_mkdir(0700, newhome, NULL); @@ -484,7 +536,7 @@ assert_false(path_rnp_file_exists(newhome, "pubring.gpg", NULL)); assert_false(path_rnp_file_exists(newhome, "secring.gpg", NULL)); /* Loading keyrings and checking whether they have correct key */ - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); keycount = 0; assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &keycount)); assert_int_equal(keycount, 2); @@ -497,7 +549,7 @@ assert_rnp_success(rnp_locate_key(rnp.ffi, "userid", "newhomekey", &handle)); assert_non_null(handle); rnp_key_handle_destroy(handle); - cli_rnp_end(&rnp); + rnp.end(); } TEST_F(rnp_tests, rnpkeys_generatekey_verifykeyHomeDirNoPermission) @@ -544,13 +596,13 @@ close(user_input_pipefd[1]); /* Mock user-input*/ - cli_rnp_cfg(*ctx).set_int(CFG_USERINPUTFD, user_input_pipefd[0]); + ctx->cfg().set_int(CFG_USERINPUTFD, user_input_pipefd[0]); if (!rnp_cmd(ctx, CMD_GENERATE_KEY, NULL)) { ret = false; goto end; } - ops.copy(cli_rnp_cfg(*ctx)); + ops.copy(ctx->cfg()); ret = true; end: /* Close & clean fd*/ @@ -689,7 +741,7 @@ assert_true(check_cfg_props(ops, "ECDSA", "ECDH", "NIST P-256", "NIST P-256", 0, 0)); assert_true(check_key_props( &rnp, "expert_ecdsa_p256", "ECDSA", "ECDH", "NIST P-256", "NIST P-256", 0, 0, "SHA256")); - cli_rnp_end(&rnp); + rnp.end(); /* ecdsa/ecdh p384 keypair */ ops.unset(CFG_USERID); @@ -700,7 +752,7 @@ &rnp, "expert_ecdsa_p256", "ECDSA", "ECDH", "NIST P-384", "NIST P-384", 0, 0, "SHA384")); assert_true(check_key_props( &rnp, "expert_ecdsa_p384", "ECDSA", "ECDH", "NIST P-384", "NIST P-384", 0, 0, "SHA384")); - cli_rnp_end(&rnp); + rnp.end(); /* ecdsa/ecdh p521 keypair */ ops.unset(CFG_USERID); @@ -709,67 +761,100 @@ assert_true(check_cfg_props(ops, "ECDSA", "ECDH", "NIST P-521", "NIST P-521", 0, 0)); assert_true(check_key_props( &rnp, "expert_ecdsa_p521", "ECDSA", "ECDH", "NIST P-521", "NIST P-521", 0, 0, "SHA512")); - cli_rnp_end(&rnp); + rnp.end(); /* ecdsa/ecdh brainpool256 keypair */ ops.unset(CFG_USERID); ops.add_str(CFG_USERID, "expert_ecdsa_bp256"); assert_true(ask_expert_details(&rnp, ops, "19\n4\n")); - assert_true( - check_cfg_props(ops, "ECDSA", "ECDH", "brainpoolP256r1", "brainpoolP256r1", 0, 0)); - assert_true(check_key_props(&rnp, - "expert_ecdsa_bp256", - "ECDSA", - "ECDH", - "brainpoolP256r1", - "brainpoolP256r1", - 0, - 0, - "SHA256")); - cli_rnp_end(&rnp); + if (brainpool_enabled()) { + assert_true( + check_cfg_props(ops, "ECDSA", "ECDH", "brainpoolP256r1", "brainpoolP256r1", 0, 0)); + assert_true(check_key_props(&rnp, + "expert_ecdsa_bp256", + "ECDSA", + "ECDH", + "brainpoolP256r1", + "brainpoolP256r1", + 0, + 0, + "SHA256")); + } else { + /* secp256k1 will be selected instead */ + assert_true(check_cfg_props(ops, "ECDSA", "ECDH", "secp256k1", "secp256k1", 0, 0)); + assert_true(check_key_props(&rnp, + "expert_ecdsa_bp256", + "ECDSA", + "ECDH", + "secp256k1", + "secp256k1", + 0, + 0, + "SHA256")); + } + rnp.end(); /* ecdsa/ecdh brainpool384 keypair */ ops.unset(CFG_USERID); ops.add_str(CFG_USERID, "expert_ecdsa_bp384"); - assert_true(ask_expert_details(&rnp, ops, "19\n5\n")); - assert_true( - check_cfg_props(ops, "ECDSA", "ECDH", "brainpoolP384r1", "brainpoolP384r1", 0, 0)); - assert_true(check_key_props(&rnp, - "expert_ecdsa_bp384", - "ECDSA", - "ECDH", - "brainpoolP384r1", - "brainpoolP384r1", - 0, - 0, - "SHA384")); - cli_rnp_end(&rnp); + if (brainpool_enabled()) { + assert_true(ask_expert_details(&rnp, ops, "19\n5\n")); + assert_true( + check_cfg_props(ops, "ECDSA", "ECDH", "brainpoolP384r1", "brainpoolP384r1", 0, 0)); + assert_true(check_key_props(&rnp, + "expert_ecdsa_bp384", + "ECDSA", + "ECDH", + "brainpoolP384r1", + "brainpoolP384r1", + 0, + 0, + "SHA384")); + } else { + assert_false(ask_expert_details(&rnp, ops, "19\n5\n")); + } + rnp.end(); /* ecdsa/ecdh brainpool512 keypair */ ops.unset(CFG_USERID); ops.add_str(CFG_USERID, "expert_ecdsa_bp512"); - assert_true(ask_expert_details(&rnp, ops, "19\n6\n")); - assert_true( - check_cfg_props(ops, "ECDSA", "ECDH", "brainpoolP512r1", "brainpoolP512r1", 0, 0)); - assert_true(check_key_props(&rnp, - "expert_ecdsa_bp512", - "ECDSA", - "ECDH", - "brainpoolP512r1", - "brainpoolP512r1", - 0, - 0, - "SHA512")); - cli_rnp_end(&rnp); + if (brainpool_enabled()) { + assert_true(ask_expert_details(&rnp, ops, "19\n6\n")); + assert_true( + check_cfg_props(ops, "ECDSA", "ECDH", "brainpoolP512r1", "brainpoolP512r1", 0, 0)); + assert_true(check_key_props(&rnp, + "expert_ecdsa_bp512", + "ECDSA", + "ECDH", + "brainpoolP512r1", + "brainpoolP512r1", + 0, + 0, + "SHA512")); + } else { + assert_false(ask_expert_details(&rnp, ops, "19\n6\n")); + } + rnp.end(); /* ecdsa/ecdh secp256k1 keypair */ ops.unset(CFG_USERID); ops.add_str(CFG_USERID, "expert_ecdsa_p256k1"); - assert_true(ask_expert_details(&rnp, ops, "19\n7\n")); - assert_true(check_cfg_props(ops, "ECDSA", "ECDH", "secp256k1", "secp256k1", 0, 0)); - assert_true(check_key_props( - &rnp, "expert_ecdsa_p256k1", "ECDSA", "ECDH", "secp256k1", "secp256k1", 0, 0, "SHA256")); - cli_rnp_end(&rnp); + if (brainpool_enabled()) { + assert_true(ask_expert_details(&rnp, ops, "19\n7\n")); + assert_true(check_cfg_props(ops, "ECDSA", "ECDH", "secp256k1", "secp256k1", 0, 0)); + assert_true(check_key_props(&rnp, + "expert_ecdsa_p256k1", + "ECDSA", + "ECDH", + "secp256k1", + "secp256k1", + 0, + 0, + "SHA256")); + } else { + assert_false(ask_expert_details(&rnp, ops, "19\n7\n")); + } + rnp.end(); /* eddsa/x25519 keypair */ ops.clear(); @@ -781,7 +866,7 @@ assert_true(check_cfg_props(ops, "EDDSA", "ECDH", NULL, "Curve25519", 0, 0)); assert_true(check_key_props( &rnp, "expert_eddsa_ecdh", "EDDSA", "ECDH", "Ed25519", "Curve25519", 0, 0, "SHA256")); - cli_rnp_end(&rnp); + rnp.end(); /* rsa/rsa 1024 key */ ops.clear(); @@ -793,7 +878,7 @@ assert_true(check_cfg_props(ops, "RSA", "RSA", NULL, NULL, 1024, 1024)); assert_true(check_key_props( &rnp, "expert_rsa_1024", "RSA", "RSA", NULL, NULL, 1024, 1024, "SHA256")); - cli_rnp_end(&rnp); + rnp.end(); /* rsa 4096 key, asked twice */ ops.unset(CFG_USERID); @@ -802,7 +887,7 @@ assert_true(check_cfg_props(ops, "RSA", "RSA", NULL, NULL, 4096, 4096)); assert_true(check_key_props( &rnp, "expert_rsa_4096", "RSA", "RSA", NULL, NULL, 4096, 4096, "SHA256")); - cli_rnp_end(&rnp); + rnp.end(); /* sm2 key */ ops.clear(); @@ -810,11 +895,15 @@ ops.set_int(CFG_S2K_ITER, 1); ops.unset(CFG_USERID); ops.add_str(CFG_USERID, "expert_sm2"); - assert_true(ask_expert_details(&rnp, ops, "99\n")); - assert_true(check_cfg_props(ops, "SM2", "SM2", NULL, NULL, 0, 0)); - assert_true(check_key_props( - &rnp, "expert_sm2", "SM2", "SM2", "SM2 P-256", "SM2 P-256", 0, 0, "SM3")); - cli_rnp_end(&rnp); + if (!sm2_enabled()) { + assert_false(ask_expert_details(&rnp, ops, "99\n")); + } else { + assert_true(ask_expert_details(&rnp, ops, "99\n")); + assert_true(check_cfg_props(ops, "SM2", "SM2", NULL, NULL, 0, 0)); + assert_true(check_key_props( + &rnp, "expert_sm2", "SM2", "SM2", "SM2 P-256", "SM2 P-256", 0, 0, "SM3")); + } + rnp.end(); } TEST_F(rnp_tests, generatekeyECDSA_explicitlySetSmallOutputDigest_DigestAlgAdjusted) @@ -837,7 +926,7 @@ 0, 0, "SHA384")); - cli_rnp_end(&rnp); + rnp.end(); } TEST_F(rnp_tests, generatekey_multipleUserIds_ShouldFail) @@ -850,7 +939,7 @@ ops.add_str(CFG_USERID, "multi_userid_1"); ops.add_str(CFG_USERID, "multi_userid_2"); assert_false(ask_expert_details(&rnp, ops, "1\n1024\n")); - cli_rnp_end(&rnp); + rnp.end(); } TEST_F(rnp_tests, generatekeyECDSA_explicitlySetBiggerThanNeededDigest_ShouldSuceed) @@ -873,7 +962,7 @@ 0, 0, "SHA512")); - cli_rnp_end(&rnp); + rnp.end(); } TEST_F(rnp_tests, generatekeyECDSA_explicitlySetUnknownDigest_ShouldFail) @@ -887,7 +976,7 @@ // Finds out that hash doesn't exist and returns an error assert_false(ask_expert_details(&rnp, ops, "19\n2\n")); - cli_rnp_end(&rnp); + rnp.end(); } /* This tests some of the mid-level key generation functions and their @@ -895,8 +984,8 @@ */ TEST_F(rnp_tests, test_generated_key_sigs) { - rnp_key_store_t *pubring = new rnp_key_store_t(); - rnp_key_store_t *secring = new rnp_key_store_t(); + rnp_key_store_t *pubring = new rnp_key_store_t(global_ctx); + rnp_key_store_t *secring = new rnp_key_store_t(global_ctx); pgp_key_t * primary_pub = NULL, *primary_sec = NULL; pgp_key_t * sub_pub = NULL, *sub_sec = NULL; @@ -913,18 +1002,18 @@ desc.crypto.key_alg = PGP_PKA_RSA; desc.crypto.rsa.modulus_bit_len = 1024; - desc.crypto.rng = &global_rng; + desc.crypto.ctx = &global_ctx; memcpy(desc.cert.userid, "test", 5); // generate - assert_true(pgp_generate_primary_key(&desc, true, &sec, &pub, PGP_KEY_STORE_GPG)); + assert_true(pgp_generate_primary_key(desc, true, sec, pub, PGP_KEY_STORE_GPG)); // add to our rings assert_true(rnp_key_store_add_key(pubring, &pub)); assert_true(rnp_key_store_add_key(secring, &sec)); // retrieve back from our rings (for later) - primary_pub = rnp_key_store_get_key_by_grip(pubring, pub.grip()); - primary_sec = rnp_key_store_get_key_by_grip(secring, pub.grip()); + primary_pub = rnp_tests_get_key_by_grip(pubring, pub.grip()); + primary_sec = rnp_tests_get_key_by_grip(secring, pub.grip()); assert_non_null(primary_pub); assert_non_null(primary_sec); assert_true(primary_pub->valid()); @@ -951,9 +1040,8 @@ // validate the userid self-sig psiginfo.sig = psig; - psiginfo.signer = &pub; - assert_rnp_success( - signature_check_certification(&psiginfo, &pub.pkt(), &pub.get_uid(0).pkt)); + pub.validate_cert(psiginfo, pub.pkt(), pub.get_uid(0).pkt, global_ctx); + assert_true(psiginfo.valid); assert_true(psig->keyfp() == pub.fp()); // check subpackets and their contents subpkt = psig->get_subpkt(PGP_SIG_SUBPKT_ISSUER_FPR); @@ -970,19 +1058,18 @@ assert_true(subpkt->fields.create <= time(NULL)); ssiginfo.sig = ssig; - ssiginfo.signer = &sec; - assert_rnp_success( - signature_check_certification(&ssiginfo, &sec.pkt(), &sec.get_uid(0).pkt)); + sec.validate_cert(ssiginfo, sec.pkt(), sec.get_uid(0).pkt, global_ctx); + assert_true(ssiginfo.valid); assert_true(ssig->keyfp() == sec.fp()); // modify a hashed portion of the sig packets psig->hashed_data[32] ^= 0xff; ssig->hashed_data[32] ^= 0xff; // ensure validation fails - assert_rnp_failure( - signature_check_certification(&psiginfo, &pub.pkt(), &pub.get_uid(0).pkt)); - assert_rnp_failure( - signature_check_certification(&ssiginfo, &sec.pkt(), &sec.get_uid(0).pkt)); + pub.validate_cert(psiginfo, pub.pkt(), pub.get_uid(0).pkt, global_ctx); + assert_false(psiginfo.valid); + sec.validate_cert(ssiginfo, sec.pkt(), sec.get_uid(0).pkt, global_ctx); + assert_false(ssiginfo.valid); // restore the original data psig->hashed_data[32] ^= 0xff; ssig->hashed_data[32] ^= 0xff; @@ -993,8 +1080,10 @@ uid.uid_len = 4; memcpy(uid.uid, "fake", 4); - assert_rnp_failure(signature_check_certification(&psiginfo, &pub.pkt(), &uid)); - assert_rnp_failure(signature_check_certification(&ssiginfo, &sec.pkt(), &uid)); + pub.validate_cert(psiginfo, pub.pkt(), uid, global_ctx); + assert_false(psiginfo.valid); + sec.validate_cert(ssiginfo, sec.pkt(), uid, global_ctx); + assert_false(ssiginfo.valid); // validate via an alternative method // primary_pub + pubring @@ -1049,11 +1138,12 @@ memset(&desc, 0, sizeof(desc)); desc.crypto.key_alg = PGP_PKA_RSA; desc.crypto.rsa.modulus_bit_len = 1024; - desc.crypto.rng = &global_rng; + desc.crypto.ctx = &global_ctx; // generate + pgp_password_provider_t prov = {}; assert_true(pgp_generate_subkey( - &desc, true, primary_sec, primary_pub, &sec, &pub, NULL, PGP_KEY_STORE_GPG)); + desc, true, *primary_sec, *primary_pub, sec, pub, prov, PGP_KEY_STORE_GPG)); assert_true(pub.valid()); assert_true(pub.validated()); assert_false(pub.expired()); @@ -1076,8 +1166,8 @@ assert_int_equal(PGP_PKT_SIGNATURE, sec.get_sig(0).rawpkt.tag); // validate the binding sig psiginfo.sig = psig; - psiginfo.signer = primary_pub; - assert_rnp_success(signature_check_binding(&psiginfo, &primary_pub->pkt(), &pub)); + primary_pub->validate_binding(psiginfo, pub, global_ctx); + assert_true(psiginfo.valid); assert_true(psig->keyfp() == primary_pub->fp()); // check subpackets and their contents subpkt = psig->get_subpkt(PGP_SIG_SUBPKT_ISSUER_FPR); @@ -1094,16 +1184,18 @@ assert_true(subpkt->fields.create <= time(NULL)); ssiginfo.sig = ssig; - ssiginfo.signer = primary_pub; - assert_rnp_success(signature_check_binding(&ssiginfo, &primary_pub->pkt(), &sec)); + primary_pub->validate_binding(ssiginfo, sec, global_ctx); + assert_true(ssiginfo.valid); assert_true(ssig->keyfp() == primary_sec->fp()); // modify a hashed portion of the sig packets psig->hashed_data[10] ^= 0xff; ssig->hashed_data[10] ^= 0xff; // ensure validation fails - assert_rnp_failure(signature_check_binding(&psiginfo, &primary_pub->pkt(), &pub)); - assert_rnp_failure(signature_check_binding(&ssiginfo, &primary_pub->pkt(), &sec)); + primary_pub->validate_binding(psiginfo, pub, global_ctx); + assert_false(psiginfo.valid); + primary_pub->validate_binding(ssiginfo, sec, global_ctx); + assert_false(ssiginfo.valid); // restore the original data psig->hashed_data[10] ^= 0xff; ssig->hashed_data[10] ^= 0xff; @@ -1112,8 +1204,8 @@ assert_true(rnp_key_store_add_key(pubring, &pub)); assert_true(rnp_key_store_add_key(secring, &sec)); // retrieve back from our rings - sub_pub = rnp_key_store_get_key_by_grip(pubring, pub.grip()); - sub_sec = rnp_key_store_get_key_by_grip(secring, pub.grip()); + sub_pub = rnp_tests_get_key_by_grip(pubring, pub.grip()); + sub_sec = rnp_tests_get_key_by_grip(secring, pub.grip()); assert_non_null(sub_pub); assert_non_null(sub_sec); assert_true(sub_pub->valid()); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/gnupg.py thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/gnupg.py --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/gnupg.py 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/gnupg.py 2022-04-15 07:49:22.000000000 +0000 @@ -1,6 +1,4 @@ -import logging import copy -import os from cli_common import run_proc class GnuPG(object): @@ -17,7 +15,6 @@ @property def common_params(self): - import copy return copy.copy(self.__common_params) @property @@ -51,6 +48,11 @@ retcode, _, _ = run_proc(cmd, params, batch_input) return retcode == 0 + def list_keys(self, secret = False): + params = ['--list-secret-keys'] if secret else ['--list-keys'] + params = params + self.common_params + return self._run(self.__gpg, params) + def generate_key_batch(self, batch_input): params = ['--gen-key', '--expert', '--batch', '--pinentry-mode', 'loopback'] + self.common_params @@ -86,6 +88,7 @@ params += ['--passphrase', self.password] params += ['--batch'] params += ['--pinentry-mode', 'loopback'] + params += ['-u', self.userid] params += ['-o', out] params += ['--sign', input] if self.hash: diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/issues/1030.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/issues/1030.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/issues/1030.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/issues/1030.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -37,10 +37,10 @@ char *home = make_temp_dir(); assert_true(setup_cli_rnp_common(&rnp, keystore, home, pipefd)); - cli_set_default_rsa_key_desc(cli_rnp_cfg(rnp), "SHA256"); + cli_set_default_rsa_key_desc(rnp.cfg(), "SHA256"); assert_true(cli_rnp_generate_key(&rnp, userid)); - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); assert_rnp_success(rnp_get_public_key_count(rnp.ffi, &keycount)); assert_int_equal(keycount, 2); assert_rnp_success(rnp_get_secret_key_count(rnp.ffi, &keycount)); @@ -65,7 +65,7 @@ if (pipefd[0] != -1) { close(pipefd[0]); } - cli_rnp_end(&rnp); + rnp.end(); free(home); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/issues/1171.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/issues/1171.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/issues/1171.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/issues/1171.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -54,8 +54,8 @@ assert_rnp_success(rnp_key_get_bits(key, &bits)); assert_int_equal(bits, 256); - /* directly use rnp_key_store_get_key_by_grip() which caused crash */ - pgp_key_t *subkey = rnp_key_store_get_key_by_grip(ffi->pubring, key->pub->grip()); + /* directly use rnp_tests_get_key_by_grip() which caused crash */ + pgp_key_t *subkey = rnp_tests_get_key_by_grip(ffi->pubring, key->pub->grip()); assert_int_equal(subkey->material().bits(), 256); assert_rnp_success(rnp_key_handle_destroy(key)); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/issues/oss-fuzz-25489.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/issues/oss-fuzz-25489.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/issues/oss-fuzz-25489.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/issues/oss-fuzz-25489.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -26,7 +26,7 @@ #include "../rnp_tests.h" #include "../support.h" -#include "librekey/key_store_g10.h" +#include "librekey/g10_sexp.hpp" TEST_F(rnp_tests, test_sxp_depth) { @@ -48,20 +48,21 @@ std::string data(mksxp(1)); bytes = &data[0]; len = data.size(); - assert_true(parse_sexp(&sxp, &bytes, &len)); - destroy_s_exp(&sxp); + s_exp_t sexp; + assert_true(sexp.parse(&bytes, &len)); } { std::string data(mksxp(SXP_MAX_DEPTH)); bytes = &data[0]; len = data.size(); - assert_true(parse_sexp(&sxp, &bytes, &len)); - destroy_s_exp(&sxp); + s_exp_t sexp; + assert_true(sexp.parse(&bytes, &len)); } { std::string data(mksxp(SXP_MAX_DEPTH + 1)); bytes = &data[0]; len = data.size(); - assert_false(parse_sexp(&sxp, &bytes, &len)); + s_exp_t sexp; + assert_false(sexp.parse(&bytes, &len)); } } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/kbx-nsigs-test.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/kbx-nsigs-test.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/kbx-nsigs-test.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/kbx-nsigs-test.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -26,6 +26,7 @@ #include #include +#include #include "rnp_tests.h" #define BLOB_HEADER_SIZE 0x5 @@ -37,12 +38,6 @@ return (uint8_t) p[0]; } -static uint16_t -ru16(uint8_t *p) -{ - return (uint16_t)(((uint8_t) p[0] << 8) | (uint8_t) p[1]); -} - static uint32_t ru32(uint8_t *p) { @@ -52,184 +47,20 @@ // This is rnp_key_store_kbx_parse_header_blob() adjusted for test static void -test_parse_header_blob(kbx_header_blob_t *first_blob) +test_parse_header_blob(kbx_header_blob_t &first_blob) { - uint8_t *image = first_blob->blob.image; - - image += BLOB_HEADER_SIZE; - - assert_int_equal(first_blob->blob.length, BLOB_FIRST_SIZE); - - first_blob->version = ru8(image); - image += 1; - - assert_int_equal(first_blob->version, 1); - - first_blob->flags = ru16(image); - image += 2; - - // blob should contains a magic KBXf - assert_memory_equal(image, "KBXf", 4); - - image += 3; - - // RFU - image += 4; - - first_blob->file_created_at = ru32(image); - image += 4; - - first_blob->file_created_at = ru32(image + 15); - image += 4; - - // RFU - image += 4; - - // RFU - image += 4; + assert_int_equal(first_blob.length(), BLOB_FIRST_SIZE); + assert_true(first_blob.parse()); } // This is rnp_key_store_kbx_parse_pgp_blob() adjusted for test static void -test_parse_pgp_blob(kbx_pgp_blob_t *pgp_blob) +test_parse_pgp_blob(kbx_pgp_blob_t &pgp_blob) { - int i; - uint8_t *image = pgp_blob->blob.image; - - image += BLOB_HEADER_SIZE; - - pgp_blob->version = ru8(image); - image += 1; - - assert_int_equal(pgp_blob->version, 1); - - pgp_blob->flags = ru16(image); - image += 2; - - pgp_blob->keyblock_offset = ru32(image); - image += 4; - - pgp_blob->keyblock_length = ru32(image); - image += 4; - - assert_false(pgp_blob->keyblock_offset > pgp_blob->blob.length || - pgp_blob->blob.length < - (pgp_blob->keyblock_offset + pgp_blob->keyblock_length)); - - pgp_blob->nkeys = ru16(image); - image += 2; - - assert_false(pgp_blob->nkeys < 1); - - pgp_blob->keys_len = ru16(image); - image += 2; - - assert_false(pgp_blob->keys_len < 28); - - for (i = 0; i < pgp_blob->nkeys; i++) { - kbx_pgp_key_t nkey = {}; - - // copy fingerprint - memcpy(nkey.fp, image, 20); - image += 20; - - nkey.keyid_offset = ru32(image); - image += 4; - - nkey.flags = ru16(image); - image += 2; - - // RFU - image += 2; - - // skip padding bytes if it existed - image += (pgp_blob->keys_len - 28); - - assert_non_null(list_append(&pgp_blob->keys, &nkey, sizeof(nkey))); - } - - pgp_blob->sn_size = ru16(image); - image += 2; - - assert_false(pgp_blob->sn_size > pgp_blob->blob.length - (image - pgp_blob->blob.image)); - - if (pgp_blob->sn_size > 0) { - pgp_blob->sn = (uint8_t *) malloc(pgp_blob->sn_size); - assert_non_null(pgp_blob->sn); - - memcpy(pgp_blob->sn, image, pgp_blob->sn_size); - image += pgp_blob->sn_size; - } - - pgp_blob->nuids = ru16(image); - image += 2; - - pgp_blob->uids_len = ru16(image); - image += 2; - - assert_false(pgp_blob->uids_len < 12); - - for (i = 0; i < pgp_blob->nuids; i++) { - kbx_pgp_uid_t nuid = {}; - - nuid.offset = ru32(image); - image += 4; - - nuid.length = ru32(image); - image += 4; - - nuid.flags = ru16(image); - image += 2; - - nuid.validity = ru8(image); - image += 1; - - // RFU - image += 1; - - // skip padding bytes if it existed - image += (pgp_blob->uids_len - 12); - - assert_non_null(list_append(&pgp_blob->uids, &nuid, sizeof(nuid))); - } - - pgp_blob->nsigs = ru16(image); - image += 2; - - pgp_blob->sigs_len = ru16(image); - image += 2; - - assert_false(pgp_blob->sigs_len < 4); - - for (i = 0; i < pgp_blob->nsigs; i++) { - kbx_pgp_sig_t nsig = {}; - - nsig.expired = ru32(image); - image += 4; - - // skip padding bytes if it existed - image += (pgp_blob->sigs_len - 4); - - assert_non_null(list_append(&pgp_blob->sigs, &nsig, sizeof(nsig))); - } - - pgp_blob->ownertrust = ru8(image); - image += 1; - - pgp_blob->all_Validity = ru8(image); - image += 1; - - // RFU - image += 2; - - pgp_blob->recheck_after = ru32(image); - image += 4; - - pgp_blob->latest_timestamp = ru32(image); - image += 4; - - pgp_blob->blob_created_at = ru32(image); - image += 4; + assert_true(pgp_blob.parse()); + assert_false(pgp_blob.keyblock_offset() > pgp_blob.length() || + pgp_blob.length() < + (pgp_blob.keyblock_offset() + pgp_blob.keyblock_length())); } // This test ensures that NSIGS field of keybox PGP blob contains the total number of @@ -277,13 +108,11 @@ assert_true(has_bytes >= BLOB_HEADER_SIZE); uint32_t blob_length = ru32(buf); assert_true(has_bytes >= blob_length); - kbx_blob_type type = (kbx_blob_type) ru8(buf + 4); + kbx_blob_type_t type = (kbx_blob_type_t) ru8(buf + 4); assert_int_equal(type, KBX_HEADER_BLOB); - kbx_header_blob_t header_blob = {}; - header_blob.blob.image = buf; - header_blob.blob.length = blob_length; - header_blob.blob.type = type; - test_parse_header_blob(&header_blob); + std::vector data(buf, buf + blob_length); + kbx_header_blob_t header_blob(data); + test_parse_header_blob(header_blob); has_bytes -= blob_length; buf += blob_length; } @@ -291,16 +120,13 @@ assert_true(has_bytes >= BLOB_HEADER_SIZE); uint32_t blob_length = ru32(buf); assert_true(has_bytes >= blob_length); - kbx_blob_type type = (kbx_blob_type) ru8(buf + 4); + kbx_blob_type_t type = (kbx_blob_type_t) ru8(buf + 4); assert_int_equal(type, KBX_PGP_BLOB); - kbx_pgp_blob_t pgp_blob = {}; - pgp_blob.blob.image = buf; - pgp_blob.blob.length = blob_length; - pgp_blob.blob.type = type; - test_parse_pgp_blob(&pgp_blob); - assert_int_equal(pgp_blob.nkeys, 2); // key and subkey - assert_int_equal(pgp_blob.nsigs, 2); // key and subkey signatures - free_kbx_pgp_blob(&pgp_blob); + std::vector data(buf, buf + blob_length); + kbx_pgp_blob_t pgp_blob(data); + test_parse_pgp_blob(pgp_blob); + assert_int_equal(pgp_blob.nkeys(), 2); // key and subkey + assert_int_equal(pgp_blob.nsigs(), 2); // key and subkey signatures has_bytes -= blob_length; buf += blob_length; } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-add-userid.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-add-userid.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-add-userid.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-add-userid.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -26,7 +26,6 @@ #include "../librekey/key_store_pgp.h" #include "pgp-key.h" - #include "rnp_tests.h" #include "support.h" #include "crypto/hash.h" @@ -47,14 +46,14 @@ "54505a936a4a970e", "326ef111425d14a5"}; - rnp_key_store_t *ks = new rnp_key_store_t(); + rnp_key_store_t *ks = new rnp_key_store_t(global_ctx); assert_rnp_success(init_file_src(&src, "data/keyrings/1/secring.gpg")); assert_rnp_success(rnp_key_store_pgp_read_from_src(ks, &src)); src_close(&src); // locate our key - assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[0], NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[0])); assert_non_null(key); // unlock the key @@ -72,7 +71,16 @@ selfsig0.key_flags = 0x2; selfsig0.key_expiration = base_expiry; selfsig0.primary = false; - assert_true(pgp_key_add_userid_certified(key, &key->pkt(), PGP_HASH_SHA1, &selfsig0)); + key->add_uid_cert(selfsig0, PGP_HASH_SHA1, global_ctx); + // attempt to add sha1-signed uid and make sure it fails + assert_int_equal(0, key->expiration()); + assert_int_equal(0x3, key->flags()); + assert_false(key->get_uid(uidc).valid); + // delete invalid uid and add valid one + key->del_uid(uidc); + assert_int_equal(uidc, key->uid_count()); + assert_int_equal(subsigc, key->sig_count()); + key->add_uid_cert(selfsig0, PGP_HASH_SHA256, global_ctx); // make sure this userid has not been marked as primary assert_false(key->has_primary_uid()); // make sure key expiration and flags are set @@ -86,7 +94,7 @@ selfsig1.key_flags = 0xAB; selfsig1.key_expiration = base_expiry + 1; selfsig1.primary = 1; - assert_true(pgp_key_add_userid_certified(key, &key->pkt(), PGP_HASH_SHA1, &selfsig1)); + key->add_uid_cert(selfsig1, PGP_HASH_SHA256, global_ctx); // make sure this userid has been marked as primary assert_int_equal(key->uid_count() - 1, key->get_primary_uid()); @@ -98,20 +106,20 @@ // try to add the same userid (should fail) rnp_selfsig_cert_info_t dup_selfsig = {}; memcpy(dup_selfsig.userid, "added1", 7); - assert_false(pgp_key_add_userid_certified(key, &key->pkt(), PGP_HASH_SHA1, &dup_selfsig)); + assert_throw(key->add_uid_cert(dup_selfsig, PGP_HASH_SHA256, global_ctx)); // try to add another primary userid (should fail) rnp_selfsig_cert_info_t selfsig2 = {}; memcpy(selfsig2.userid, "added2", 7); selfsig2.primary = 1; - assert_false(pgp_key_add_userid_certified(key, &key->pkt(), PGP_HASH_SHA1, &selfsig2)); + assert_throw(key->add_uid_cert(selfsig2, PGP_HASH_SHA256, global_ctx)); memcpy(selfsig2.userid, "added2", 7); selfsig2.key_flags = 0xCD; selfsig2.primary = 0; // actually add another userid - assert_true(pgp_key_add_userid_certified(key, &key->pkt(), PGP_HASH_SHA1, &selfsig2)); + key->add_uid_cert(selfsig2, PGP_HASH_SHA256, global_ctx); // confirm that the counts have increased as expected assert_int_equal(key->uid_count(), uidc + 3); @@ -143,14 +151,14 @@ key = NULL; // start over - ks = new rnp_key_store_t(); + ks = new rnp_key_store_t(global_ctx); assert_non_null(ks); // read from the saved packets assert_rnp_success(init_mem_src(&src, mem_dest_get_memory(&dst), dst.writeb, false)); assert_rnp_success(rnp_key_store_pgp_read_from_src(ks, &src)); src_close(&src); dst_close(&dst, true); - assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[0], NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[0])); // confirm that the counts have increased as expected assert_int_equal(key->uid_count(), uidc + 3); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-grip.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-grip.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-grip.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-grip.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -34,126 +34,122 @@ TEST_F(rnp_tests, key_grip) { - pgp_key_grip_t grip; - const pgp_key_t *key; - rnp_key_store_t *pub_store = NULL; - rnp_key_store_t *sec_store = NULL; - - pub_store = - new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/test_stream_key_load/g10/pubring.kbx"); + rnp_key_store_t *pub_store = new rnp_key_store_t( + PGP_KEY_STORE_KBX, "data/test_stream_key_load/g10/pubring.kbx", global_ctx); assert_true(rnp_key_store_load_from_path(pub_store, NULL)); - sec_store = new rnp_key_store_t(PGP_KEY_STORE_G10, - "data/test_stream_key_load/g10/private-keys-v1.d"); + rnp_key_store_t *sec_store = new rnp_key_store_t( + PGP_KEY_STORE_G10, "data/test_stream_key_load/g10/private-keys-v1.d", global_ctx); pgp_key_provider_t key_provider = {.callback = rnp_key_provider_store, .userdata = pub_store}; assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); + const pgp_key_t *key = NULL; // dsa-eg public/secret key - assert_true( - rnp::hex_decode("552286BEB2999F0A9E26A50385B90D9724001187", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("A5E4CD2CBBE44A16E4D6EC05C2E3C3A599DC763C", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "552286BEB2999F0A9E26A50385B90D9724001187")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "552286BEB2999F0A9E26A50385B90D9724001187")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "A5E4CD2CBBE44A16E4D6EC05C2E3C3A599DC763C")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "A5E4CD2CBBE44A16E4D6EC05C2E3C3A599DC763C")); // rsa/rsa public/secret key - assert_true( - rnp::hex_decode("D148210FAF36468055B83D0F5A6DEB83FBC8E864", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("CED7034A8EB5F4CE90DF99147EC33D86FCD3296C", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "D148210FAF36468055B83D0F5A6DEB83FBC8E864")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "D148210FAF36468055B83D0F5A6DEB83FBC8E864")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "CED7034A8EB5F4CE90DF99147EC33D86FCD3296C")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "CED7034A8EB5F4CE90DF99147EC33D86FCD3296C")); // ed25519 : public/secret key - assert_true( - rnp::hex_decode("940D97D75C306D737A59A98EAFF1272832CEDC0B", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "940D97D75C306D737A59A98EAFF1272832CEDC0B")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "940D97D75C306D737A59A98EAFF1272832CEDC0B")); // x25519 : public/secret key/subkey - assert_true( - rnp::hex_decode("A77DC8173DA6BEE126F5BD6F5A14E01200B52FCE", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("636C983EDB558527BA82780B52CB5DAE011BE46B", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "A77DC8173DA6BEE126F5BD6F5A14E01200B52FCE")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "A77DC8173DA6BEE126F5BD6F5A14E01200B52FCE")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "636C983EDB558527BA82780B52CB5DAE011BE46B")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "636C983EDB558527BA82780B52CB5DAE011BE46B")); // nistp256 : public/secret key/subkey - assert_true( - rnp::hex_decode("FC81AECE90BCE6E54D0D637D266109783AC8DAC0", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("A56DC8DB8355747A809037459B4258B8A743EAB5", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "FC81AECE90BCE6E54D0D637D266109783AC8DAC0")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "FC81AECE90BCE6E54D0D637D266109783AC8DAC0")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "A56DC8DB8355747A809037459B4258B8A743EAB5")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "A56DC8DB8355747A809037459B4258B8A743EAB5")); // nistp384 : public/secret key/subkey - assert_true( - rnp::hex_decode("A1338230AED1C9C125663518470B49056C9D1733", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("797A83FE041FFE06A7F4B1D32C6F4AE0F6D87ADF", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "A1338230AED1C9C125663518470B49056C9D1733")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "A1338230AED1C9C125663518470B49056C9D1733")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "797A83FE041FFE06A7F4B1D32C6F4AE0F6D87ADF")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "797A83FE041FFE06A7F4B1D32C6F4AE0F6D87ADF")); // nistp521 : public/secret key/subkey - assert_true( - rnp::hex_decode("D91B789603EC9138AA20342A2B6DC86C81B70F5D", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("FD048B2CA1919CB241DC8A2C7FA3E742EF343DCA", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "D91B789603EC9138AA20342A2B6DC86C81B70F5D")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "D91B789603EC9138AA20342A2B6DC86C81B70F5D")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "FD048B2CA1919CB241DC8A2C7FA3E742EF343DCA")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "FD048B2CA1919CB241DC8A2C7FA3E742EF343DCA")); // brainpool256 : public/secret key/subkey - assert_true( - rnp::hex_decode("A01BAA22A72F09A0FF0A1D4CBCE70844DD52DDD7", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("C1678B7DE5F144C93B89468D5F9764ACE182ED36", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "A01BAA22A72F09A0FF0A1D4CBCE70844DD52DDD7")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "A01BAA22A72F09A0FF0A1D4CBCE70844DD52DDD7")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "C1678B7DE5F144C93B89468D5F9764ACE182ED36")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "C1678B7DE5F144C93B89468D5F9764ACE182ED36")); // brainpool384 : public/secret key/subkey - assert_true( - rnp::hex_decode("2F25DB025DEBF3EA2715350209B985829B04F50A", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("B6BD8B81F75AF914163D97DF8DE8F6FC64C283F8", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "2F25DB025DEBF3EA2715350209B985829B04F50A")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "2F25DB025DEBF3EA2715350209B985829B04F50A")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "B6BD8B81F75AF914163D97DF8DE8F6FC64C283F8")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "B6BD8B81F75AF914163D97DF8DE8F6FC64C283F8")); // brainpool512 : public/secret key/subkey - assert_true( - rnp::hex_decode("5A484F56AB4B8B6583B6365034999F6543FAE1AE", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("9133E4A7E8FC8515518DF444C3F2F247EEBBADEC", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "5A484F56AB4B8B6583B6365034999F6543FAE1AE")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "5A484F56AB4B8B6583B6365034999F6543FAE1AE")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "9133E4A7E8FC8515518DF444C3F2F247EEBBADEC")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "9133E4A7E8FC8515518DF444C3F2F247EEBBADEC")); // secp256k1 : public/secret key/subkey - assert_true( - rnp::hex_decode("498B89C485489BA16B40755C0EBA580166393074", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); - assert_true( - rnp::hex_decode("48FFED40D018747363BDEFFDD404D1F4870F8064", grip.data(), grip.size())); - assert_non_null(key = rnp_key_store_get_key_by_grip(pub_store, grip)); - assert_non_null(key = rnp_key_store_get_key_by_grip(sec_store, grip)); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "498B89C485489BA16B40755C0EBA580166393074")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "498B89C485489BA16B40755C0EBA580166393074")); + assert_non_null( + key = rnp_tests_get_key_by_grip(pub_store, "48FFED40D018747363BDEFFDD404D1F4870F8064")); + assert_non_null( + key = rnp_tests_get_key_by_grip(sec_store, "48FFED40D018747363BDEFFDD404D1F4870F8064")); // cleanup delete pub_store; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-protect.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-protect.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-protect.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-protect.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -50,16 +50,15 @@ // load our keyring and do some quick checks { pgp_source_t src = {}; - rnp_key_store_t *ks = new rnp_key_store_t(); + rnp_key_store_t *ks = new rnp_key_store_t(global_ctx); assert_rnp_success(init_file_src(&src, "data/keyrings/1/secring.gpg")); assert_rnp_success(rnp_key_store_pgp_read_from_src(ks, &src)); src_close(&src); for (size_t i = 0; i < ARRAY_SIZE(keyids); i++) { - pgp_key_t * key = NULL; - const char *keyid = keyids[i]; - assert_non_null(key = rnp_tests_get_key_by_id(ks, keyid, NULL)); + pgp_key_t *key = NULL; + assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[i])); assert_non_null(key); // all keys in this keyring are encrypted and thus should be both protected and // locked initially @@ -68,7 +67,7 @@ } pgp_key_t *tmp = NULL; - assert_non_null(tmp = rnp_tests_get_key_by_id(ks, keyids[0], NULL)); + assert_non_null(tmp = rnp_tests_get_key_by_id(ks, keyids[0])); // steal this key from the store key = new pgp_key_t(*tmp); @@ -87,15 +86,15 @@ // try to unprotect with a failing password provider pgp_password_provider_t pprov = {.callback = failing_password_callback, .userdata = NULL}; - assert_false(key->unprotect(pprov)); + assert_false(key->unprotect(pprov, global_ctx.rng)); // try to unprotect with an incorrect password pprov = {.callback = string_copy_password_callback, .userdata = (void *) "badpass"}; - assert_false(key->unprotect(pprov)); + assert_false(key->unprotect(pprov, global_ctx.rng)); // unprotect with the correct password pprov = {.callback = string_copy_password_callback, .userdata = (void *) "password"}; - assert_true(key->unprotect(pprov)); + assert_true(key->unprotect(pprov, global_ctx.rng)); assert_false(key->is_protected()); // should still be locked @@ -127,7 +126,7 @@ // confirm that packets[0] is no longer encrypted { pgp_source_t memsrc = {}; - rnp_key_store_t *ks = new rnp_key_store_t(); + rnp_key_store_t *ks = new rnp_key_store_t(global_ctx); pgp_rawpacket_t &pkt = key->rawpkt(); assert_rnp_success(init_mem_src(&memsrc, pkt.raw.data(), pkt.raw.size(), false)); @@ -136,7 +135,7 @@ // grab the first key pgp_key_t *reloaded_key = NULL; - assert_non_null(reloaded_key = rnp_tests_get_key_by_id(ks, keyids[0], NULL)); + assert_non_null(reloaded_key = rnp_tests_get_key_by_id(ks, keyids[0])); assert_non_null(reloaded_key); // should not be locked, nor protected @@ -183,7 +182,7 @@ // try to protect (will fail when key is locked) pprov = {.callback = string_copy_password_callback, .userdata = (void *) "newpass"}; - assert_false(key->protect({}, pprov)); + assert_false(key->protect({}, pprov, global_ctx.rng)); assert_false(key->is_protected()); // unlock @@ -193,12 +192,12 @@ // try to protect with a failing password provider pprov = {.callback = failing_password_callback, .userdata = NULL}; - assert_false(key->protect({}, pprov)); + assert_false(key->protect({}, pprov, global_ctx.rng)); assert_false(key->is_protected()); // (re)protect with a new password pprov = {.callback = string_copy_password_callback, .userdata = (void *) "newpass"}; - assert_true(key->protect({}, pprov)); + assert_true(key->protect({}, pprov, global_ctx.rng)); assert_true(key->is_protected()); // lock @@ -227,24 +226,21 @@ TEST_F(rnp_tests, test_key_protect_sec_data) { - rng_t rng; - assert_true(rng_init(&rng, RNG_DRBG)); - rnp_keygen_primary_desc_t pri_desc = {}; pri_desc.crypto.key_alg = PGP_PKA_RSA; pri_desc.crypto.rsa.modulus_bit_len = 1024; - pri_desc.crypto.rng = &rng; + pri_desc.crypto.ctx = &global_ctx; memcpy(pri_desc.cert.userid, "test", 5); rnp_keygen_subkey_desc_t sub_desc = {}; sub_desc.crypto.key_alg = PGP_PKA_RSA; sub_desc.crypto.rsa.modulus_bit_len = 1024; - sub_desc.crypto.rng = &rng; + sub_desc.crypto.ctx = &global_ctx; /* generate raw unprotected keypair */ pgp_key_t skey, pkey, ssub, psub; assert_true(pgp_generate_keypair( - &rng, &pri_desc, &sub_desc, true, &skey, &pkey, &ssub, &psub, PGP_KEY_STORE_GPG)); + pri_desc, sub_desc, true, skey, pkey, ssub, psub, PGP_KEY_STORE_GPG)); assert_non_null(skey.pkt().sec_data); assert_non_null(ssub.pkt().sec_data); assert_null(pkey.pkt().sec_data); @@ -292,8 +288,8 @@ pgp_password_provider_t pprov = {.callback = string_copy_password_callback, .userdata = (void *) "password"}; rnp_key_protection_params_t prot = {}; - assert_true(skey.protect(prot, pprov)); - assert_true(ssub.protect(prot, pprov)); + assert_true(skey.protect(prot, pprov, global_ctx.rng)); + assert_true(ssub.protect(prot, pprov, global_ctx.rng)); assert_int_not_equal(memcmp(raw_skey, skey.pkt().sec_data, 32), 0); assert_int_not_equal(memcmp(raw_ssub, ssub.pkt().sec_data, 32), 0); #if defined(__has_feature) @@ -327,15 +323,15 @@ assert_int_not_equal(memcmp(raw_skey, skey.pkt().sec_data, 32), 0); assert_int_not_equal(memcmp(raw_ssub, ssub.pkt().sec_data, 32), 0); /* unprotect key */ - assert_true(skey.unprotect(pprov)); - assert_true(ssub.unprotect(pprov)); + assert_true(skey.unprotect(pprov, global_ctx.rng)); + assert_true(ssub.unprotect(pprov, global_ctx.rng)); assert_int_equal(memcmp(raw_skey, skey.pkt().sec_data, 32), 0); assert_int_equal(memcmp(raw_ssub, ssub.pkt().sec_data, 32), 0); /* protect it back with another password */ pgp_password_provider_t pprov2 = {.callback = string_copy_password_callback, .userdata = (void *) "password2"}; - assert_true(skey.protect(prot, pprov2)); - assert_true(ssub.protect(prot, pprov2)); + assert_true(skey.protect(prot, pprov2, global_ctx.rng)); + assert_true(ssub.protect(prot, pprov2, global_ctx.rng)); assert_int_not_equal(memcmp(raw_skey, skey.pkt().sec_data, 32), 0); assert_int_not_equal(memcmp(raw_ssub, ssub.pkt().sec_data, 32), 0); assert_false(skey.unlock(pprov)); @@ -361,6 +357,4 @@ assert_int_not_equal(memcmp(raw_ssub, ssubpkt->sec_data, 32), 0); assert_int_equal(ssubpkt->sec_protection.s2k.specifier, PGP_S2KS_ITERATED_AND_SALTED); delete ssubpkt; - - rng_destroy(&rng); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-store-search.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-store-search.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-store-search.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-store-search.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -38,7 +38,7 @@ TEST_F(rnp_tests, test_key_store_search) { // create our store - rnp_key_store_t *store = new rnp_key_store_t(PGP_KEY_STORE_GPG, ""); + rnp_key_store_t *store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); store->disable_validation = true; // some fake key data @@ -73,12 +73,14 @@ fp.fingerprint[0] = (uint8_t) n; fp.length = PGP_FINGERPRINT_SIZE; // set the userids - pgp_transferable_key_t tkey; for (size_t uidn = 0; testdata[i].userids[uidn]; uidn++) { - pgp_transferable_userid_t *uid = - transferable_key_add_userid(tkey, testdata[i].userids[uidn]); - assert_non_null(uid); - key.add_uid(*uid); + pgp_transferable_userid_t tuid; + tuid.uid.tag = PGP_PKT_USER_ID; + tuid.uid.uid_len = strlen(testdata[i].userids[uidn]); + tuid.uid.uid = (uint8_t *) malloc(tuid.uid.uid_len); + assert_non_null(tuid.uid.uid); + memcpy(tuid.uid.uid, testdata[i].userids[uidn], tuid.uid.uid_len); + key.add_uid(tuid); } // add to the store assert_true(rnp_key_store_add_key(store, &key)); @@ -87,13 +89,12 @@ // keyid search for (size_t i = 0; i < ARRAY_SIZE(testdata); i++) { - pgp_key_id_t keyid = {}; - assert_true(rnp::hex_decode(testdata[i].keyid, keyid.data(), keyid.size())); + std::string keyid = testdata[i].keyid; std::set seen_keys; - for (pgp_key_t *key = rnp_key_store_get_key_by_id(store, keyid, NULL); key; - key = rnp_key_store_get_key_by_id(store, keyid, key)) { + for (pgp_key_t *key = rnp_tests_get_key_by_id(store, keyid); key; + key = rnp_tests_get_key_by_id(store, keyid, key)) { // check that the keyid actually matches - assert_true(key->keyid() == keyid); + assert_true(cmp_keyid(key->keyid(), keyid)); // check that we have not already encountered this key pointer assert_int_equal(seen_keys.count(key), 0); // keep track of what key pointers we have seen @@ -105,13 +106,10 @@ for (size_t i = 0; i < ARRAY_SIZE(testdata); i++) { std::set seen_keys; pgp_key_t * key = NULL; - key = rnp_tests_get_key_by_id(store, testdata[i].keyid, NULL); + key = rnp_tests_get_key_by_id(store, testdata[i].keyid); while (key) { // check that the keyid actually matches - pgp_key_id_t expected_keyid = {}; - assert_true(rnp::hex_decode( - testdata[i].keyid, expected_keyid.data(), expected_keyid.size())); - assert_true(key->keyid() == expected_keyid); + assert_true(cmp_keyid(key->keyid(), testdata[i].keyid)); // check that we have not already encountered this key pointer assert_int_equal(seen_keys.count(key), 0); // keep track of what key pointers we have seen @@ -168,11 +166,11 @@ // load pubring rnp_key_store_t *pub_store = - new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx"); + new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); assert_true(rnp_key_store_load_from_path(pub_store, NULL)); // load secring rnp_key_store_t *sec_store = - new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d"); + new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); pgp_key_provider_t key_provider = {.callback = rnp_key_provider_store, .userdata = pub_store}; assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); @@ -186,12 +184,12 @@ /* Find keys and subkeys by fingerprint, id and userid */ primsec = rnp_tests_get_key_by_fpr(sec_store, "4F2E62B74E6A4CD333BC19004BE147BB22DF1E60"); assert_non_null(primsec); - key = rnp_tests_get_key_by_id(sec_store, "4BE147BB22DF1E60", NULL); + key = rnp_tests_get_key_by_id(sec_store, "4BE147BB22DF1E60"); assert_true(key == primsec); subsec = rnp_tests_get_key_by_fpr(sec_store, "10793E367EE867C32E358F2AA49BAE05C16E8BC8"); assert_non_null(subsec); assert_true(primsec != subsec); - key = rnp_tests_get_key_by_id(sec_store, "A49BAE05C16E8BC8", NULL); + key = rnp_tests_get_key_by_id(sec_store, "A49BAE05C16E8BC8"); assert_true(key == subsec); primpub = rnp_tests_get_key_by_fpr(pub_store, "4F2E62B74E6A4CD333BC19004BE147BB22DF1E60"); @@ -208,31 +206,31 @@ assert_true(key == primsec); key = rnp_tests_get_key_by_fpr(sec_store, "0x4f2e62b74e6a4cd333bc19004be147bb22df1e60"); assert_true(key == primsec); - key = rnp_tests_get_key_by_id(pub_store, "4BE147BB22DF1E60", NULL); - assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, "4be147bb22df1e60", NULL); - assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, "0x4be147bb22df1e60", NULL); + key = rnp_tests_get_key_by_id(pub_store, "4BE147BB22DF1E60"); assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, "22df1e60", NULL); + key = rnp_tests_get_key_by_id(pub_store, "4be147bb22df1e60"); assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, "0x22df1e60", NULL); + key = rnp_tests_get_key_by_id(pub_store, "0x4be147bb22df1e60"); assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, "4be1 47bb 22df 1e60", NULL); + key = rnp_tests_get_key_by_id(pub_store, "22df1e60"); + assert_null(key); + key = rnp_tests_get_key_by_id(pub_store, "0x22df1e60"); + assert_null(key); + key = rnp_tests_get_key_by_id(pub_store, "4be1 47bb 22df 1e60"); assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, "4be147bb 22df1e60", NULL); + key = rnp_tests_get_key_by_id(pub_store, "4be147bb 22df1e60"); assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, " 4be147bb\t22df1e60 ", NULL); + key = rnp_tests_get_key_by_id(pub_store, " 4be147bb\t22df1e60 "); assert_true(key == primpub); - key = rnp_tests_get_key_by_id(pub_store, "test1", NULL); + key = rnp_tests_get_key_by_id(pub_store, "test1"); assert_null(key); /* Try negative searches */ assert_null(rnp_tests_get_key_by_fpr(sec_store, "4f2e62b74e6a4cd333bc19004be147bb22df1e")); assert_null(rnp_tests_get_key_by_fpr(sec_store, "2e62b74e6a4cd333bc19004be147bb22df1e60")); - assert_null(rnp_tests_get_key_by_id(sec_store, "4be147bb22dfle60", NULL)); - assert_null(rnp_tests_get_key_by_id(sec_store, "", NULL)); - assert_null(rnp_tests_get_key_by_id(sec_store, "test11", NULL)); - assert_null(rnp_tests_get_key_by_id(sec_store, "atest1", NULL)); + assert_null(rnp_tests_get_key_by_id(sec_store, "4be147bb22dfle60")); + assert_null(rnp_tests_get_key_by_id(sec_store, "")); + assert_null(rnp_tests_get_key_by_id(sec_store, "test11")); + assert_null(rnp_tests_get_key_by_id(sec_store, "atest1")); // cleanup delete pub_store; diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-unlock.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-unlock.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-unlock.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-unlock.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -47,7 +47,7 @@ "326ef111425d14a5"}; assert_true(setup_cli_rnp_common(&rnp, RNP_KEYSTORE_GPG, "data/keyrings/1/", NULL)); - assert_true(cli_rnp_load_keyrings(&rnp, true)); + assert_true(rnp.load_keyrings(true)); for (size_t i = 0; i < ARRAY_SIZE(keyids); i++) { rnp_key_handle_t handle = NULL; @@ -67,10 +67,10 @@ // try signing with a failing password provider (should fail) assert_rnp_success( rnp_ffi_set_pass_provider(rnp.ffi, ffi_failing_password_provider, NULL)); - rnp_cfg &cfg = cli_rnp_cfg(rnp); + rnp_cfg &cfg = rnp.cfg(); cfg.load_defaults(); cfg.set_bool(CFG_SIGN_NEEDED, true); - cfg.set_str(CFG_HASH, "SHA1"); + cfg.set_str(CFG_HASH, "SHA256"); cfg.set_int(CFG_ZLEVEL, 0); cfg.set_str(CFG_INFILE, "dummyfile.dat"); cfg.set_str(CFG_OUTFILE, "dummyfile.dat.pgp"); @@ -127,7 +127,7 @@ cfg.clear(); cfg.load_defaults(); cfg.set_bool(CFG_SIGN_NEEDED, true); - cfg.set_str(CFG_HASH, "SHA1"); + cfg.set_str(CFG_HASH, "SHA256"); cfg.set_int(CFG_ZLEVEL, 0); cfg.set_str(CFG_INFILE, "dummyfile.dat"); cfg.set_str(CFG_OUTFILE, "dummyfile.dat.pgp"); @@ -217,6 +217,6 @@ // cleanup assert_rnp_success(rnp_key_handle_destroy(key)); assert_rnp_success(rnp_key_handle_destroy(subkey)); - cli_rnp_end(&rnp); + rnp.end(); assert_int_equal(rnp_unlink("dummyfile.dat"), 0); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-validate.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-validate.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/key-validate.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/key-validate.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -57,39 +57,50 @@ rnp_key_store_t *secring; pgp_key_t * key = NULL; - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); /* this keyring has one expired subkey */ - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "1d7e8a5393c997a8", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "1d7e8a5393c997a8")); assert_false(key->valid()); assert_true(key->expired()); assert_true(all_keys_valid(pubring, key)); delete pubring; - /* secret key doesn't have expired binding signature so considered as valid */ - secring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/secring.gpg"); + /* secret key is marked is expired as well */ + secring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/secring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(secring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(secring, "1d7e8a5393c997a8", NULL)); - assert_true(key->valid()); - assert_false(key->expired()); - assert_true(all_keys_valid(secring)); + assert_non_null(key = rnp_tests_get_key_by_id(secring, "1d7e8a5393c997a8")); + assert_false(key->valid()); + assert_true(key->expired()); + assert_true(all_keys_valid(secring, key)); delete secring; - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_true(all_keys_valid(pubring)); - delete pubring; - secring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/secring.gpg"); + /* secret keyring doesn't have signatures - so keys are marked as invalid */ + secring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/secring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(secring, NULL)); + assert_false(all_keys_valid(secring)); + /* but after adding signatures from public it is marked as valid */ + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "dc70c124a50283f1")); + assert_non_null(rnp_key_store_import_key(secring, key, true, NULL)); assert_true(all_keys_valid(secring)); + delete pubring; delete secring; - pubring = new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_true(all_keys_valid(pubring)); - secring = new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d"); + secring = + new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); pgp_key_provider_t key_provider = {.callback = rnp_key_provider_store, .userdata = pubring}; assert_true(rnp_key_store_load_from_path(secring, &key_provider)); @@ -97,22 +108,42 @@ delete pubring; delete secring; - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/pubring.pgp"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/pubring.pgp", global_ctx); + assert_true(rnp_key_store_load_from_path(pubring, NULL)); + /* certification has signature with MD5 hash algorithm */ + assert_false(all_keys_valid(pubring)); + + rnp_key_store_clear(pubring); + /* add rule which allows MD5 */ + rnp::SecurityRule allow_md5( + rnp::FeatureType::Hash, PGP_HASH_MD5, rnp::SecurityLevel::Default); + allow_md5.override = true; + global_ctx.profile.add_rule(allow_md5); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_true(all_keys_valid(pubring)); + rnp_key_store_clear(pubring); + /* remove rule */ + assert_true(global_ctx.profile.del_rule(allow_md5)); + assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_false(all_keys_valid(pubring)); delete pubring; - secring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/secring.pgp"); + /* secret keyring doesn't have certifications - so marked as invalid */ + secring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/secring.pgp", global_ctx); assert_true(rnp_key_store_load_from_path(secring, NULL)); - assert_true(all_keys_valid(secring)); + assert_false(all_keys_valid(secring)); delete secring; - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/5/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/5/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_true(all_keys_valid(pubring)); delete pubring; - secring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/5/secring.gpg"); + secring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/5/secring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(secring, NULL)); assert_true(all_keys_valid(secring)); delete secring; @@ -135,7 +166,7 @@ static bool key_check(rnp_key_store_t *keyring, const std::string &keyid, bool valid, bool expired = false) { - pgp_key_t *key = rnp_tests_get_key_by_id(keyring, keyid, NULL); + pgp_key_t *key = rnp_tests_get_key_by_id(keyring, keyid); return key && (key->validated()) && (key->valid() == valid) && (key->expired() == expired); } @@ -144,7 +175,7 @@ rnp_key_store_t *pubring; pgp_key_t * key = NULL; - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, ""); + pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); /* load valid dsa-eg key */ key_store_add(pubring, DATA_PATH "dsa-eg-pub.pgp"); @@ -160,10 +191,10 @@ /* load dsa-eg key with forged key material */ key_store_add(pubring, DATA_PATH "dsa-eg-pub-forged-material.pgp"); - key = rnp_tests_get_key_by_id(pubring, "C8A10A7D78273E10", NULL); + key = rnp_tests_get_key_by_id(pubring, "C8A10A7D78273E10"); assert_null(key); /* malformed key material causes keyid change */ - key = rnp_tests_get_key_by_id(pubring, "C258AB3B54097B9B", NULL); + key = rnp_tests_get_key_by_id(pubring, "C258AB3B54097B9B"); assert_non_null(key); assert_false(key->valid()); assert_false(key->expired()); @@ -187,7 +218,7 @@ /* load eddsa key with forged key material */ key_store_add(pubring, DATA_PATH "ecc-25519-pub-forged-material.pgp"); - key = rnp_tests_get_key_by_id(pubring, "1BEF78DF765B79A2", NULL); + key = rnp_tests_get_key_by_id(pubring, "1BEF78DF765B79A2"); assert_non_null(key); assert_false(key->valid()); assert_false(key->expired()); @@ -208,9 +239,9 @@ /* load ecdsa/ecdh key with forged key material. Subkey is not valid as well. */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-forged-material.pgp"); - key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL); + key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527"); assert_null(key); - key = rnp_tests_get_key_by_id(pubring, "41DEA786D18E5184", NULL); + key = rnp_tests_get_key_by_id(pubring, "41DEA786D18E5184"); assert_non_null(key); assert_false(key->valid()); assert_false(key->expired()); @@ -243,8 +274,14 @@ /* load valid rsa/rsa keypair */ key_store_add(pubring, DATA_PATH "rsa-rsa-pub.pgp"); - assert_true(key_check(pubring, "2FB9179118898E8B", true)); - assert_true(key_check(pubring, "6E2F73008F8B8D6E", true)); + /* it is invalid since SHA1 hash is used for signatures */ + assert_false(key_check(pubring, "2FB9179118898E8B", true)); + assert_false(key_check(pubring, "6E2F73008F8B8D6E", true)); + /* allow SHA1 within further checks */ + rnp::SecurityRule allow_sha1( + rnp::FeatureType::Hash, PGP_HASH_SHA1, rnp::SecurityLevel::Default, 1547856001); + global_ctx.profile.add_rule(allow_sha1); + rnp_key_store_clear(pubring); /* load rsa/rsa key with forged self-signature. Valid because of valid binding. */ @@ -255,9 +292,9 @@ /* load rsa/rsa key with forged key material. Subkey is not valid as well. */ key_store_add(pubring, DATA_PATH "rsa-rsa-pub-forged-material.pgp"); - key = rnp_tests_get_key_by_id(pubring, "2FB9179118898E8B", NULL); + key = rnp_tests_get_key_by_id(pubring, "2FB9179118898E8B"); assert_null(key); - key = rnp_tests_get_key_by_id(pubring, "791B14952D8F906C", NULL); + key = rnp_tests_get_key_by_id(pubring, "791B14952D8F906C"); assert_non_null(key); assert_false(key->valid()); assert_false(key->expired()); @@ -276,6 +313,9 @@ assert_true(key_check(pubring, "021085B640CE8DCE", false)); rnp_key_store_clear(pubring); + /* remove SHA1 rule */ + assert_true(global_ctx.profile.del_rule(allow_sha1)); + /* load eddsa/rsa keypair with certification with future creation date - valid because of * binding. */ key_store_add(pubring, DATA_PATH "ecc-25519-pub-future-cert.pgp"); @@ -317,7 +357,8 @@ * Alice is signed by Basil, but without the Basil's key. * Result: Alice [valid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case1/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case1/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); @@ -330,9 +371,10 @@ * corrupted. * Result: Alice [invalid], Basil [valid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case2/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case2/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_false(key->expired()); assert_non_null(key = rnp_tests_key_search(pubring, "Basil ")); @@ -345,9 +387,10 @@ * Alice is signed by Basil, but doesn't have self-signature * Result: Alice [invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case3/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case3/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_false(key->expired()); assert_non_null(key = rnp_tests_key_search(pubring, "Basil ")); @@ -360,7 +403,8 @@ * Alice subkey has invalid binding signature * Result: Alice [valid], Alice sub [invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case4/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case4/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); @@ -380,7 +424,8 @@ * Note: to re-generate keyring file, use generate.cpp from case5 folder. * To build it, feed -DBUILD_TESTING_GENERATORS=On to the cmake. */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case5/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case5/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); @@ -396,7 +441,8 @@ * Key Alice has revocation signature by Alice, and subkey doesn't * Result: Alice [invalid], Alice sub [invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case6/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case6/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_false(key->valid()); @@ -414,7 +460,8 @@ * Alice subkey has revocation signature by Alice * Result: Alice [valid], Alice sub [invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case7/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case7/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); @@ -432,9 +479,10 @@ * Userid is stripped from the key, but it still has valid subkey binding * Result: Alice [valid], Alice sub[valid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case8/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case8/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_true(key->valid()); assert_int_equal(key->subkey_count(), 1); assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); @@ -447,10 +495,11 @@ * expiration. * Result: Alice [valid], Alice sub[valid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case9/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case9/pubring.gpg", global_ctx); assert_non_null(pubring); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_true(key->valid()); assert_false(key->expired()); assert_int_equal(key->subkey_count(), 1); @@ -464,10 +513,11 @@ * Alice key has expiring direct-key signature and non-expiring self-certification. * Result: Alice [invalid], Alice sub[invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case10/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case10/pubring.gpg", global_ctx); assert_non_null(pubring); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->subkey_count(), 1); @@ -481,10 +531,11 @@ * Alice key has expiring direct-key signature, non-expiring self-certification and * expiring primary userid certification. Result: Alice [invalid], Alice sub[invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case11/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case11/pubring.gpg", global_ctx); assert_non_null(pubring); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 100); @@ -499,10 +550,11 @@ * Alice key has non-expiring direct-key signature, non-expiring self-certification and * expiring primary userid certification. Result: Alice [invalid], Alice sub[invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case12/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case12/pubring.gpg", global_ctx); assert_non_null(pubring); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 2000); @@ -517,10 +569,11 @@ * Alice key has expiring direct-key signature, non-expiring self-certification and * non-expiring primary userid certification. Result: Alice [invalid], Alice sub[invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case13/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case13/pubring.gpg", global_ctx); assert_non_null(pubring); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 6); @@ -536,10 +589,11 @@ * non-expiring primary userid certification (with 0 key expiration subpacket). Result: * Alice [invalid], Alice sub[invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case14/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case14/pubring.gpg", global_ctx); assert_non_null(pubring); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 6); @@ -554,10 +608,11 @@ * Signing subkey has expired primary-key signature embedded into the subkey binding. * Result: primary [valid], sub[invalid] */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case15/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case15/pubring.gpg", global_ctx); assert_non_null(pubring); assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_non_null(key = rnp_tests_get_key_by_id(pubring, "E863072D3E9042EE", NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubring, "E863072D3E9042EE")); assert_true(key->valid()); assert_false(key->expired()); assert_int_equal(key->expiration(), 0); @@ -572,7 +627,7 @@ { /* this test was mainly used to generate test data for cases 10-12 in test_key_validity */ rnp_key_store_t *secring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp"); + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp", global_ctx); assert_true(rnp_key_store_load_from_path(secring, NULL)); pgp_key_t *key = NULL; assert_non_null(key = rnp_tests_key_search(secring, "Alice ")); @@ -593,17 +648,17 @@ pgp_password_provider_t pprov = {.callback = string_copy_password_callback, .userdata = (void *) "password"}; key->unlock(pprov); - assert_true(signature_calculate_direct(&key->pkt(), &sig, &key->pkt())); + key->sign_direct(key->pkt(), sig, global_ctx); key->add_sig(sig, PGP_UID_NONE); key->revalidate(*secring); - /* key is still valid since it is secret */ + /* key becomsed invalid even since it is secret */ assert_int_equal(key->expiration(), 1000); - assert_true(key->valid()); - assert_false(key->expired()); + assert_false(key->valid()); + assert_true(key->expired()); rnp_key_store_t *pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp"); + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); pgp_key_t *pubkey = NULL; assert_non_null(pubkey = rnp_tests_key_search(pubring, "Alice ")); @@ -611,7 +666,7 @@ assert_true(pubkey->valid()); assert_false(pubkey->expired()); pgp_key_t *subpub = NULL; - assert_non_null(subpub = rnp_tests_get_key_by_id(pubring, "dd23ceb7febeff17", NULL)); + assert_non_null(subpub = rnp_tests_get_key_by_id(pubring, "dd23ceb7febeff17")); assert_int_equal(subpub->expiration(), 0); assert_true(subpub->valid()); assert_false(subpub->expired()); @@ -631,17 +686,18 @@ memcpy(selfsig1.userid, boris, strlen(boris)); selfsig1.key_expiration = 100; selfsig1.primary = true; - assert_true(pgp_key_add_userid_certified(key, &key->pkt(), PGP_HASH_SHA256, &selfsig1)); + key->add_uid_cert(selfsig1, PGP_HASH_SHA256, global_ctx); key->revalidate(*secring); - /* key is still valid since it is secret, however expiration was changed */ + /* key becomes invalid even it is secret */ assert_int_equal(key->expiration(), 100); - assert_true(key->valid()); - assert_false(key->expired()); + assert_false(key->valid()); + assert_true(key->expired()); delete secring; delete pubring; - secring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp"); + secring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp", global_ctx); assert_true(rnp_key_store_load_from_path(secring, NULL)); assert_non_null(key = rnp_tests_key_search(secring, "Alice ")); /* create direct-key signature */ @@ -656,7 +712,7 @@ sig.set_keyid(key->keyid()); key->unlock(pprov); - assert_true(signature_calculate_direct(&key->pkt(), &sig, &key->pkt())); + key->sign_direct(key->pkt(), sig, global_ctx); key->add_sig(sig, PGP_UID_NONE); key->revalidate(*secring); assert_int_equal(key->expiration(), 6); @@ -665,14 +721,15 @@ memcpy(selfsig1.userid, boris, strlen(boris)); selfsig1.key_expiration = 0; selfsig1.primary = true; - assert_true(pgp_key_add_userid_certified(key, &key->pkt(), PGP_HASH_SHA256, &selfsig1)); + key->add_uid_cert(selfsig1, PGP_HASH_SHA256, global_ctx); key->revalidate(*secring); assert_int_equal(key->expiration(), 6); - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_non_null(pubkey = rnp_tests_key_search(pubring, "Alice ")); - assert_non_null(subpub = rnp_tests_get_key_by_id(pubring, "dd23ceb7febeff17", NULL)); + assert_non_null(subpub = rnp_tests_get_key_by_id(pubring, "dd23ceb7febeff17")); assert_int_equal(subpub->expiration(), 0); assert_true(subpub->valid()); assert_false(subpub->expired()); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/load-g10.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/load-g10.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/load-g10.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/load-g10.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -33,20 +33,15 @@ static bool test_load_g10_check_key(rnp_key_store_t *pub, rnp_key_store_t *sec, const char *id) { - pgp_key_id_t keyid = {}; - pgp_key_t * key = NULL; - pgp_password_provider_t pswd_prov = {.callback = string_copy_password_callback, - .userdata = (void *) "password"}; - - if (!rnp::hex_decode(id, keyid.data(), keyid.size())) { - return false; - } - if (!rnp_key_store_get_key_by_id(pub, keyid, NULL)) { + pgp_key_t *key = rnp_tests_get_key_by_id(pub, id); + if (!key) { return false; } - if (!(key = rnp_key_store_get_key_by_id(sec, keyid, NULL))) { + if (!(key = rnp_tests_get_key_by_id(sec, id))) { return false; } + pgp_password_provider_t pswd_prov = {.callback = string_copy_password_callback, + .userdata = (void *) "password"}; return key->is_protected() && key->unlock(pswd_prov) && key->lock(); } @@ -60,10 +55,12 @@ pgp_key_provider_t key_provider = {.callback = rnp_key_provider_store, .userdata = NULL}; // load pubring - pub_store = new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx"); + pub_store = + new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); assert_true(rnp_key_store_load_from_path(pub_store, NULL)); // load secring - sec_store = new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d"); + sec_store = + new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); key_provider.userdata = pub_store; assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); @@ -76,11 +73,11 @@ delete sec_store; /* another store */ - pub_store = - new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/test_stream_key_load/g10/pubring.kbx"); + pub_store = new rnp_key_store_t( + PGP_KEY_STORE_KBX, "data/test_stream_key_load/g10/pubring.kbx", global_ctx); assert_true(rnp_key_store_load_from_path(pub_store, NULL)); - sec_store = new rnp_key_store_t(PGP_KEY_STORE_G10, - "data/test_stream_key_load/g10/private-keys-v1.d"); + sec_store = new rnp_key_store_t( + PGP_KEY_STORE_G10, "data/test_stream_key_load/g10/private-keys-v1.d", global_ctx); key_provider.userdata = pub_store; assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); @@ -92,6 +89,10 @@ assert_true(test_load_g10_check_key(pub_store, sec_store, "2FB9179118898E8B")); assert_true(test_load_g10_check_key(pub_store, sec_store, "6E2F73008F8B8D6E")); + /* rsa/rsa new key. Now fails since uses new s-exp syntax */ + assert_false(test_load_g10_check_key(pub_store, sec_store, "BD860A52D1899C0F")); + assert_false(test_load_g10_check_key(pub_store, sec_store, "8E08D46A37414996")); + /* ed25519 key */ assert_true(test_load_g10_check_key(pub_store, sec_store, "CC786278981B0728")); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/load-pgp.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/load-pgp.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/load-pgp.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/load-pgp.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -40,7 +40,7 @@ { pgp_source_t src = {}; - rnp_key_store_t *key_store = new rnp_key_store_t(); + rnp_key_store_t *key_store = new rnp_key_store_t(global_ctx); // load pubring in to the key store assert_rnp_success(init_file_src(&src, "data/keyrings/2/pubring.gpg")); @@ -49,8 +49,7 @@ assert_int_equal(1, rnp_key_store_get_key_count(key_store)); // find the key by keyid - static const pgp_key_id_t keyid = {0xDC, 0x70, 0xC1, 0x24, 0xA5, 0x02, 0x83, 0xF1}; - const pgp_key_t * key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + const pgp_key_t *key = rnp_tests_get_key_by_id(key_store, "DC70C124A50283F1"); assert_non_null(key); // confirm the key flags are correct @@ -65,15 +64,14 @@ // load secret keyring and decrypt the key - key_store = new rnp_key_store_t(); + key_store = new rnp_key_store_t(global_ctx); assert_rnp_success(init_file_src(&src, "data/keyrings/4/secring.pgp")); assert_rnp_success(rnp_key_store_pgp_read_from_src(key_store, &src)); src_close(&src); assert_int_equal(1, rnp_key_store_get_key_count(key_store)); - static const pgp_key_id_t keyid2 = {0x7D, 0x0B, 0xC1, 0x0E, 0x93, 0x34, 0x04, 0xC9}; - key = rnp_key_store_get_key_by_id(key_store, keyid2, NULL); + key = rnp_tests_get_key_by_id(key_store, "7D0BC10E933404C9"); assert_non_null(key); // confirm the key flags are correct @@ -85,9 +83,7 @@ assert_true(key->is_locked()); // decrypt the key - const pgp_rawpacket_t &pkt = key->rawpkt(); - pgp_key_pkt_t * seckey = - pgp_decrypt_seckey_pgp(pkt.raw.data(), pkt.raw.size(), &key->pkt(), "password"); + pgp_key_pkt_t *seckey = pgp_decrypt_seckey_pgp(key->rawpkt(), key->pkt(), "password"); assert_non_null(seckey); // cleanup @@ -103,7 +99,7 @@ { pgp_source_t src = {}; - rnp_key_store_t *key_store = new rnp_key_store_t(); + rnp_key_store_t *key_store = new rnp_key_store_t(global_ctx); // load it in to the key store assert_rnp_success(init_file_src(&src, "data/keyrings/1/pubring.gpg")); @@ -112,8 +108,8 @@ assert_int_equal(7, rnp_key_store_get_key_count(key_store)); // find the key by keyid - static const pgp_key_id_t keyid = {0x8a, 0x05, 0xb8, 0x9f, 0xad, 0x5a, 0xde, 0xd1}; - const pgp_key_t * key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + static const std::string keyid = "8a05b89fad5aded1"; + const pgp_key_t * key = rnp_tests_get_key_by_id(key_store, keyid); assert_non_null(key); // confirm the key flags are correct @@ -130,7 +126,7 @@ const unsigned subkey_counts[]) { pgp_source_t src = {}; - rnp_key_store_t *key_store = new rnp_key_store_t(); + rnp_key_store_t *key_store = new rnp_key_store_t(global_ctx); // load it in to the key store assert_rnp_success(init_file_src(&src, path)); @@ -187,19 +183,17 @@ */ TEST_F(rnp_tests, test_load_check_bitfields_and_times) { - pgp_key_id_t keyid = {}; const pgp_key_t * key; const pgp_signature_t *sig = NULL; // load keyring rnp_key_store_t *key_store = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg"); + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(key_store, NULL)); // find key = NULL; - assert_true(rnp::hex_decode("7BC6709B15C23A4A", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "7BC6709B15C23A4A"); assert_non_null(key); // check subsig count assert_int_equal(key->sig_count(), 3); @@ -208,7 +202,7 @@ sig = &key->get_sig(i).sig; static const time_t expected_creation_times[] = {1500569820, 1500569836, 1500569846}; // check SS_ISSUER_KEY_ID - assert_true(keyid == sig->keyid()); + assert_true(cmp_keyid(sig->keyid(), "7BC6709B15C23A4A")); // check SS_CREATION_TIME assert_int_equal(sig->creation(), expected_creation_times[i]); // check SS_EXPIRATION_TIME @@ -219,15 +213,13 @@ // find key = NULL; - assert_true(rnp::hex_decode("1ED63EE56FADC34D", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "1ED63EE56FADC34D"); assert_non_null(key); // check subsig count assert_int_equal(key->sig_count(), 1); sig = &key->get_sig(0).sig; // check SS_ISSUER_KEY_ID - assert_true(rnp::hex_decode("7BC6709B15C23A4A", keyid.data(), keyid.size())); - assert_true(keyid == sig->keyid()); + assert_true(cmp_keyid(sig->keyid(), "7BC6709B15C23A4A")); // check SS_CREATION_TIME [0] assert_int_equal(sig->creation(), 1500569820); assert_int_equal(sig->creation(), key->creation()); @@ -238,15 +230,13 @@ // find key = NULL; - assert_true(rnp::hex_decode("1D7E8A5393C997A8", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "1D7E8A5393C997A8"); assert_non_null(key); // check subsig count assert_int_equal(key->sig_count(), 1); sig = &key->get_sig(0).sig; // check SS_ISSUER_KEY_ID - assert_true(rnp::hex_decode("7BC6709B15C23A4A", keyid.data(), keyid.size())); - assert_true(keyid == sig->keyid()); + assert_true(cmp_keyid(sig->keyid(), "7BC6709B15C23A4A")); // check SS_CREATION_TIME [0] assert_int_equal(sig->creation(), 1500569851); assert_int_equal(sig->creation(), key->creation()); @@ -257,15 +247,13 @@ // find key = NULL; - assert_true(rnp::hex_decode("8A05B89FAD5ADED1", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "8A05B89FAD5ADED1"); assert_non_null(key); // check subsig count assert_int_equal(key->sig_count(), 1); sig = &key->get_sig(0).sig; // check SS_ISSUER_KEY_ID - assert_true(rnp::hex_decode("7BC6709B15C23A4A", keyid.data(), keyid.size())); - assert_true(keyid == sig->keyid()); + assert_true(cmp_keyid(sig->keyid(), "7BC6709B15C23A4A")); // check SS_CREATION_TIME [0] assert_int_equal(sig->creation(), 1500569896); assert_int_equal(sig->creation(), key->creation()); @@ -276,11 +264,9 @@ // find key = NULL; - assert_true(rnp::hex_decode("2FCADF05FFA501BB", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "2FCADF05FFA501BB"); assert_non_null(key); // check subsig count - assert_int_equal(key->sig_count(), 3); // check subsig properties for (size_t i = 0; i < key->sig_count(); i++) { @@ -288,7 +274,7 @@ static const time_t expected_creation_times[] = {1501372449, 1500570153, 1500570147}; // check SS_ISSUER_KEY_ID - assert_true(keyid == sig->keyid()); + assert_true(cmp_keyid(sig->keyid(), "2FCADF05FFA501BB")); // check SS_CREATION_TIME assert_int_equal(sig->creation(), expected_creation_times[i]); // check SS_EXPIRATION_TIME @@ -299,15 +285,13 @@ // find key = NULL; - assert_true(rnp::hex_decode("54505A936A4A970E", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "54505A936A4A970E"); assert_non_null(key); // check subsig count assert_int_equal(key->sig_count(), 1); sig = &key->get_sig(0).sig; // check SS_ISSUER_KEY_ID - assert_true(rnp::hex_decode("2FCADF05FFA501BB", keyid.data(), keyid.size())); - assert_true(keyid == sig->keyid()); + assert_true(cmp_keyid(sig->keyid(), "2FCADF05FFA501BB")); // check SS_CREATION_TIME [0] assert_int_equal(sig->creation(), 1500569946); assert_int_equal(sig->creation(), key->creation()); @@ -318,15 +302,13 @@ // find key = NULL; - assert_true(rnp::hex_decode("326EF111425D14A5", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "326EF111425D14A5"); assert_non_null(key); // check subsig count assert_int_equal(key->sig_count(), 1); sig = &key->get_sig(0).sig; // check SS_ISSUER_KEY_ID - assert_true(rnp::hex_decode("2FCADF05FFA501BB", keyid.data(), keyid.size())); - assert_true(keyid == sig->keyid()); + assert_true(cmp_keyid(sig->keyid(), "2FCADF05FFA501BB")); // check SS_CREATION_TIME [0] assert_int_equal(sig->creation(), 1500570165); assert_int_equal(sig->creation(), key->creation()); @@ -350,13 +332,13 @@ // load keyring rnp_key_store_t *key_store = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg"); + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(key_store, NULL)); // find key = NULL; assert_true(rnp::hex_decode("DC70C124A50283F1", keyid.data(), keyid.size())); - key = rnp_key_store_get_key_by_id(key_store, keyid, NULL); + key = rnp_tests_get_key_by_id(key_store, "DC70C124A50283F1"); assert_non_null(key); // check key version assert_int_equal(key->version(), PGP_V3); @@ -385,18 +367,15 @@ TEST_F(rnp_tests, test_load_armored_pub_sec) { - pgp_key_t * key; - pgp_key_id_t keyid = {}; - rnp_key_store_t *key_store; - - key_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, MERGE_PATH "key-both.asc"); + rnp_key_store_t *key_store = + new rnp_key_store_t(PGP_KEY_STORE_GPG, MERGE_PATH "key-both.asc", global_ctx); assert_true(rnp_key_store_load_from_path(key_store, NULL)); /* we must have 1 main key and 2 subkeys */ assert_int_equal(rnp_key_store_get_key_count(key_store), 3); - assert_true(rnp::hex_decode("9747D2A6B3A63124", keyid.data(), keyid.size())); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + pgp_key_t *key = NULL; + assert_non_null(key = rnp_tests_get_key_by_id(key_store, "9747D2A6B3A63124")); assert_true(key->valid()); assert_true(key->is_primary()); assert_true(key->is_secret()); @@ -407,8 +386,7 @@ assert_int_equal(key->get_uid(1).rawpkt.tag, PGP_PKT_USER_ID); assert_int_equal(key->get_sig(1).rawpkt.tag, PGP_PKT_SIGNATURE); - assert_true(rnp::hex_decode("AF1114A47F5F5B28", keyid.data(), keyid.size())); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, "AF1114A47F5F5B28")); assert_true(key->valid()); assert_true(key->is_subkey()); assert_true(key->is_secret()); @@ -416,8 +394,7 @@ assert_int_equal(key->rawpkt().tag, PGP_PKT_SECRET_SUBKEY); assert_int_equal(key->get_sig(0).rawpkt.tag, PGP_PKT_SIGNATURE); - assert_true(rnp::hex_decode("16CD16F267CCDD4F", keyid.data(), keyid.size())); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, "16CD16F267CCDD4F")); assert_true(key->valid()); assert_true(key->is_subkey()); assert_true(key->is_secret()); @@ -425,6 +402,11 @@ assert_int_equal(key->rawpkt().tag, PGP_PKT_SECRET_SUBKEY); assert_int_equal(key->get_sig(0).rawpkt.tag, PGP_PKT_SIGNATURE); + /* make sure half of keyid doesn't work */ + assert_null(key = rnp_tests_get_key_by_id(key_store, "0000000016CD16F2")); + assert_null(key = rnp_tests_get_key_by_id(key_store, "67CCDD4F00000000")); + assert_null(key = rnp_tests_get_key_by_id(key_store, "0000000067CCDD4F")); + /* both user ids should be present */ assert_non_null(rnp_tests_key_search(key_store, "key-merge-uid-1")); assert_non_null(rnp_tests_key_search(key_store, "key-merge-uid-2")); @@ -474,26 +456,22 @@ TEST_F(rnp_tests, test_load_merge) { pgp_key_t * key, *skey1, *skey2; - pgp_key_id_t keyid = {}; - pgp_key_id_t sub1id = {}; - pgp_key_id_t sub2id = {}; - rnp_key_store_t * key_store; pgp_transferable_key_t tkey = {}; pgp_transferable_subkey_t tskey = {}; pgp_password_provider_t provider = {}; provider.callback = string_copy_password_callback; provider.userdata = (void *) "password"; - key_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, ""); - assert_true(rnp::hex_decode("9747D2A6B3A63124", keyid.data(), keyid.size())); - assert_true(rnp::hex_decode("AF1114A47F5F5B28", sub1id.data(), sub1id.size())); - assert_true(rnp::hex_decode("16CD16F267CCDD4F", sub2id.data(), sub2id.size())); + rnp_key_store_t *key_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); + std::string keyid = "9747D2A6B3A63124"; + std::string sub1id = "AF1114A47F5F5B28"; + std::string sub2id = "16CD16F267CCDD4F"; /* load just key packet */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-just-key.pgp")); assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 1); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_false(key->valid()); assert_int_equal(key->rawpkt_count(), 1); assert_int_equal(key->rawpkt().tag, PGP_PKT_PUBLIC_KEY); @@ -502,20 +480,20 @@ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-uid-1-no-sigs.pgp")); assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 1); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_false(key->valid()); assert_int_equal(key->uid_count(), 1); assert_int_equal(key->rawpkt_count(), 2); assert_int_equal(key->rawpkt().tag, PGP_PKT_PUBLIC_KEY); assert_int_equal(key->get_uid(0).rawpkt.tag, PGP_PKT_USER_ID); assert_null(rnp_tests_key_search(key_store, "key-merge-uid-1")); - assert_true(key == rnp_tests_get_key_by_id(key_store, "9747D2A6B3A63124", NULL)); + assert_true(key == rnp_tests_get_key_by_id(key_store, "9747D2A6B3A63124")); /* load key + user id 1 with sigs */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-uid-1.pgp")); assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 1); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_true(key->valid()); assert_int_equal(key->uid_count(), 1); assert_int_equal(key->rawpkt_count(), 3); @@ -530,7 +508,7 @@ /* try to add it twice */ assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 1); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_true(key->valid()); assert_int_equal(key->uid_count(), 2); assert_int_equal(key->rawpkt_count(), 5); @@ -546,8 +524,8 @@ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-subkey-1-no-sigs.pgp")); assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 2); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_true(key->valid()); assert_false(skey1->valid()); assert_int_equal(key->uid_count(), 2); @@ -569,8 +547,8 @@ /* try to add it twice */ assert_true(rnp_key_store_add_transferable_subkey(key_store, &tskey, key)); assert_int_equal(rnp_key_store_get_key_count(key_store), 2); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_true(key->valid()); assert_true(skey1->valid()); assert_int_equal(key->uid_count(), 2); @@ -593,9 +571,9 @@ /* try to add it twice */ assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 3); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); - assert_non_null(skey2 = rnp_key_store_get_key_by_id(key_store, sub2id, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); + assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); assert_true(key->valid()); assert_true(skey1->valid()); assert_true(skey2->valid()); @@ -624,9 +602,9 @@ /* try to add it twice */ assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 3); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); - assert_non_null(skey2 = rnp_key_store_get_key_by_id(key_store, sub2id, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); + assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); assert_true(key->valid()); assert_true(skey1->valid()); assert_true(skey2->valid()); @@ -659,9 +637,9 @@ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-sec.asc")); assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); assert_int_equal(rnp_key_store_get_key_count(key_store), 3); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); - assert_non_null(skey2 = rnp_key_store_get_key_by_id(key_store, sub2id, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); + assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); assert_true(key->valid()); assert_true(skey1->valid()); assert_true(skey2->valid()); @@ -691,26 +669,23 @@ TEST_F(rnp_tests, test_load_public_from_secret) { - pgp_key_t * key, *skey1, *skey2, keycp; - pgp_key_id_t keyid = {}; - pgp_key_id_t sub1id = {}; - pgp_key_id_t sub2id = {}; - rnp_key_store_t *secstore, *pubstore; - - secstore = new rnp_key_store_t(PGP_KEY_STORE_GPG, MERGE_PATH "key-sec.asc"); + rnp_key_store_t *secstore = + new rnp_key_store_t(PGP_KEY_STORE_GPG, MERGE_PATH "key-sec.asc", global_ctx); assert_true(rnp_key_store_load_from_path(secstore, NULL)); - pubstore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "pubring.gpg"); + rnp_key_store_t *pubstore = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "pubring.gpg", global_ctx); - assert_true(rnp::hex_decode("9747D2A6B3A63124", keyid.data(), keyid.size())); - assert_true(rnp::hex_decode("AF1114A47F5F5B28", sub1id.data(), sub1id.size())); - assert_true(rnp::hex_decode("16CD16F267CCDD4F", sub2id.data(), sub2id.size())); - - assert_non_null(key = rnp_key_store_get_key_by_id(secstore, keyid, NULL)); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(secstore, sub1id, NULL)); - assert_non_null(skey2 = rnp_key_store_get_key_by_id(secstore, sub2id, NULL)); + std::string keyid = "9747D2A6B3A63124"; + std::string sub1id = "AF1114A47F5F5B28"; + std::string sub2id = "16CD16F267CCDD4F"; + + pgp_key_t *key = NULL, *skey1 = NULL, *skey2 = NULL; + assert_non_null(key = rnp_tests_get_key_by_id(secstore, keyid)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(secstore, sub1id)); + assert_non_null(skey2 = rnp_tests_get_key_by_id(secstore, sub2id)); /* copy the secret key */ - keycp = pgp_key_t(*key, false); + pgp_key_t keycp = pgp_key_t(*key, false); assert_true(keycp.is_secret()); assert_int_equal(keycp.subkey_count(), 2); assert_true(keycp.get_subkey_fp(0) == skey1->fp()); @@ -736,7 +711,7 @@ assert_int_equal(keycp.subkey_count(), 0); assert_true(check_subkey_fp(key, &keycp, 0)); assert_true(keycp.grip() == skey1->grip()); - assert_true(keycp.keyid() == sub1id); + assert_true(cmp_keyid(keycp.keyid(), sub1id)); assert_int_equal(keycp.rawpkt().tag, PGP_PKT_PUBLIC_SUBKEY); assert_null(keycp.pkt().sec_data); assert_int_equal(keycp.pkt().sec_len, 0); @@ -748,7 +723,7 @@ assert_int_equal(keycp.subkey_count(), 0); assert_true(check_subkey_fp(key, &keycp, 1)); assert_true(keycp.grip() == skey2->grip()); - assert_true(keycp.keyid() == sub2id); + assert_true(cmp_keyid(keycp.keyid(), sub2id)); assert_int_equal(keycp.rawpkt().tag, PGP_PKT_PUBLIC_SUBKEY); assert_null(keycp.pkt().sec_data); assert_int_equal(keycp.pkt().sec_len, 0); @@ -758,11 +733,11 @@ assert_true(rnp_key_store_write_to_path(pubstore)); delete pubstore; /* reload */ - pubstore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "pubring.gpg"); + pubstore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubstore, NULL)); - assert_non_null(key = rnp_key_store_get_key_by_id(pubstore, keyid, NULL)); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(pubstore, sub1id, NULL)); - assert_non_null(skey2 = rnp_key_store_get_key_by_id(pubstore, sub2id, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(pubstore, keyid)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(pubstore, sub1id)); + assert_non_null(skey2 = rnp_tests_get_key_by_id(pubstore, sub2id)); delete pubstore; delete secstore; @@ -779,7 +754,7 @@ assert_true(setup_cli_rnp_common(&rnp, RNP_KEYSTORE_GPG, ".rnp", NULL)); /* import just the public key */ - rnp_cfg &cfg = cli_rnp_cfg(rnp); + rnp_cfg &cfg = rnp.cfg(); cfg.set_str(CFG_KEYFILE, MERGE_PATH "key-pub-just-key.pgp"); assert_true(cli_rnp_add_key(&rnp)); assert_true(cli_rnp_save_keyrings(&rnp)); @@ -944,26 +919,21 @@ assert_int_equal(tskey->subkey.tag, PGP_PKT_SECRET_SUBKEY); assert_rnp_success(decrypt_secret_key(&tskey->subkey, "password")); - cli_rnp_end(&rnp); + rnp.end(); } TEST_F(rnp_tests, test_load_subkey) { - pgp_key_t * key, *skey1, *skey2; - pgp_key_id_t keyid = {}; - pgp_key_id_t sub1id = {}; - pgp_key_id_t sub2id = {}; - rnp_key_store_t *key_store; - - key_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, ""); - assert_true(rnp::hex_decode("9747D2A6B3A63124", keyid.data(), keyid.size())); - assert_true(rnp::hex_decode("AF1114A47F5F5B28", sub1id.data(), sub1id.size())); - assert_true(rnp::hex_decode("16CD16F267CCDD4F", sub2id.data(), sub2id.size())); + rnp_key_store_t *key_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); + std::string keyid = "9747D2A6B3A63124"; + std::string sub1id = "AF1114A47F5F5B28"; + std::string sub2id = "16CD16F267CCDD4F"; /* load first subkey with signature */ + pgp_key_t *key = NULL, *skey1 = NULL, *skey2 = NULL; assert_true(load_keystore(key_store, MERGE_PATH "key-pub-just-subkey-1.pgp")); assert_int_equal(rnp_key_store_get_key_count(key_store), 1); - assert_non_null(skey1 = rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); + assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_false(skey1->valid()); assert_int_equal(skey1->rawpkt_count(), 2); assert_int_equal(skey1->rawpkt().tag, PGP_PKT_PUBLIC_SUBKEY); @@ -973,7 +943,7 @@ /* load second subkey, without signature */ assert_true(load_keystore(key_store, MERGE_PATH "key-pub-just-subkey-2-no-sigs.pgp")); assert_int_equal(rnp_key_store_get_key_count(key_store), 2); - assert_non_null(skey2 = rnp_key_store_get_key_by_id(key_store, sub2id, NULL)); + assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); assert_false(skey2->valid()); assert_int_equal(skey2->rawpkt_count(), 1); assert_int_equal(skey2->rawpkt().tag, PGP_PKT_PUBLIC_SUBKEY); @@ -983,14 +953,14 @@ /* load primary key without subkey signatures */ assert_true(load_keystore(key_store, MERGE_PATH "key-pub-uid-1.pgp")); assert_int_equal(rnp_key_store_get_key_count(key_store), 3); - assert_non_null(key = rnp_key_store_get_key_by_id(key_store, keyid, NULL)); + assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_true(key->valid()); assert_int_equal(key->rawpkt_count(), 3); assert_int_equal(key->rawpkt().tag, PGP_PKT_PUBLIC_KEY); assert_int_equal(key->get_uid(0).rawpkt.tag, PGP_PKT_USER_ID); assert_int_equal(key->get_sig(0).rawpkt.tag, PGP_PKT_SIGNATURE); - assert_true(skey1 == rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); - assert_true(skey2 == rnp_key_store_get_key_by_id(key_store, sub2id, NULL)); + assert_true(skey1 == rnp_tests_get_key_by_id(key_store, sub1id)); + assert_true(skey2 == rnp_tests_get_key_by_id(key_store, sub2id)); assert_true(skey1->has_primary_fp()); assert_true(check_subkey_fp(key, skey1, 0)); assert_int_equal(key->subkey_count(), 1); @@ -1000,9 +970,9 @@ /* load second subkey with signature */ assert_true(load_keystore(key_store, MERGE_PATH "key-pub-just-subkey-2.pgp")); assert_int_equal(rnp_key_store_get_key_count(key_store), 3); - assert_true(key == rnp_key_store_get_key_by_id(key_store, keyid, NULL)); - assert_true(skey1 == rnp_key_store_get_key_by_id(key_store, sub1id, NULL)); - assert_true(skey2 == rnp_key_store_get_key_by_id(key_store, sub2id, NULL)); + assert_true(key == rnp_tests_get_key_by_id(key_store, keyid)); + assert_true(skey1 == rnp_tests_get_key_by_id(key_store, sub1id)); + assert_true(skey2 == rnp_tests_get_key_by_id(key_store, sub2id)); assert_true(skey2->has_primary_fp()); assert_true(check_subkey_fp(key, skey2, 1)); assert_int_equal(key->subkey_count(), 2); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rng-randomness.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rng-randomness.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rng-randomness.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rng-randomness.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017-2022 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "rnp_tests.h" +#include +#include "support.h" + +TEST_F(rnp_tests, test_rng_randomness) +{ + uint8_t samples[4096]; + + memset(samples, 0, sizeof(samples)); + + // Repetition Count Test, see NIST SP 800-90B + const size_t C = 6; // cutoff value + size_t B = 1; + uint8_t A; + global_ctx.rng.get(samples, sizeof(samples)); + A = samples[0]; + for (size_t i = 1; i < sizeof(samples); i++) { + if (samples[i] == A) { + B++; + assert_int_not_equal(B, C); + } else { + A = samples[i]; + B = 1; + } + } +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rnp.py thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rnp.py --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rnp.py 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rnp.py 2022-04-15 07:49:22.000000000 +0000 @@ -3,7 +3,6 @@ run_proc ) import os -import logging import copy class Rnp(object): @@ -58,6 +57,11 @@ retcode, _, _ = run_proc(cmd, params, batch_input) return retcode == 0 + def list_keys(self, secret = False): + params = ['--list-keys', '--secret'] if secret else ['--list-keys'] + params = params + self.common_params + return self._run(self.key_mgm_bin, params) + def generate_key_batch(self, batch_input): pipe = pswd_pipe(self.__password) params = self.common_params @@ -76,7 +80,7 @@ params = self.common_params params += ["--output", output] params += ["--userid", self.userid] - params += ["--force"] + params += ["--overwrite"] params += ["--export-key"] if secure: params += ["--secret"] diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rnp_tests.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rnp_tests.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rnp_tests.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rnp_tests.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -34,7 +34,7 @@ /* * Handler used to access DRBG. */ -rng_t global_rng; +rnp::SecurityContext global_ctx; rnp_tests::rnp_tests() : m_dir(make_temp_dir()) { diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rnp_tests.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rnp_tests.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/rnp_tests.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/rnp_tests.h 2022-04-15 07:49:22.000000000 +0000 @@ -339,6 +339,8 @@ void test_ffi_remove_signatures(void **state); +void test_ffi_backend_version(void **state); + void test_ffi_remove_uid(void **state); void test_rnp_mkstemp(void **state); @@ -455,6 +457,8 @@ void test_fuzz_verify_detached(void **state); +void test_rng_randomness(void **state); + #define assert_true(a) EXPECT_TRUE((a)) #define assert_false(a) EXPECT_FALSE((a)) #define assert_string_equal(a, b) EXPECT_STREQ((a), (b)) @@ -467,5 +471,6 @@ #define assert_rnp_failure(a) EXPECT_NE((a), RNP_SUCCESS) #define assert_memory_equal(a, b, sz) EXPECT_EQ(0, memcmp((a), (b), (sz))) #define assert_memory_not_equal(a, b, sz) EXPECT_NE(0, memcmp((a), (b), (sz))) +#define assert_throw(a) EXPECT_ANY_THROW((a)) #endif // RNP_TESTS_H diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/streams.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/streams.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/streams.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/streams.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -43,27 +43,23 @@ #include "time-utils.h" static bool -stream_hash_file(pgp_hash_t *hash, const char *path) +stream_hash_file(rnp::Hash &hash, const char *path) { - uint8_t readbuf[1024]; pgp_source_t src; - bool res = false; - if (init_file_src(&src, path)) { return false; } + bool res = false; do { - size_t read = 0; + uint8_t readbuf[1024]; + size_t read = 0; if (!src_read(&src, readbuf, sizeof(readbuf), &read)) { goto finish; } else if (read == 0) { break; } - - if (pgp_hash_add(hash, readbuf, read)) { - goto finish; - } + hash.add(readbuf, read); } while (1); res = true; @@ -168,14 +164,14 @@ copy_tmp_path(char *buf, size_t buflen, pgp_dest_t *dst) { typedef struct pgp_dest_file_param_t { - int fd; - int errcode; - bool overwrite; - char path[PATH_MAX]; + int fd; + int errcode; + bool overwrite; + std::string path; } pgp_dest_file_param_t; pgp_dest_file_param_t *param = (pgp_dest_file_param_t *) dst->param; - strncpy(buf, param->path, buflen); + strncpy(buf, param->path.c_str(), buflen); } TEST_F(rnp_tests, test_stream_file) @@ -186,7 +182,7 @@ const char * filedata = "dummy message to be stored in the file"; const int iterations = 10000; const int filedatalen = strlen(filedata); - char tmpname[PATH_MAX] = {0}; + char tmpname[128] = {0}; uint8_t tmpbuf[1024] = {0}; pgp_dest_t dst = {}; pgp_source_t src = {}; @@ -341,46 +337,42 @@ rnp_key_store_t *pubring; rnp_key_store_t *secring; pgp_signature_t sig; - pgp_hash_t hash_orig; - pgp_hash_t hash_forged; - pgp_hash_t hash; - pgp_hash_alg_t halg; pgp_source_t sigsrc; pgp_key_t * key = NULL; - rng_t rng; - /* we need rng for key validation */ - assert_true(rng_init(&rng, RNG_SYSTEM)); /* load keys */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/test_stream_signatures/pub.asc"); + pubring = new rnp_key_store_t( + PGP_KEY_STORE_GPG, "data/test_stream_signatures/pub.asc", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); /* load signature */ assert_rnp_success(init_file_src(&sigsrc, "data/test_stream_signatures/source.txt.sig")); assert_rnp_success(sig.parse(sigsrc)); src_close(&sigsrc); /* hash signed file */ - halg = sig.halg; - assert_true(pgp_hash_create(&hash_orig, halg)); - assert_true(stream_hash_file(&hash_orig, "data/test_stream_signatures/source.txt")); + pgp_hash_alg_t halg = sig.halg; + rnp::Hash hash_orig(halg); + assert_true(stream_hash_file(hash_orig, "data/test_stream_signatures/source.txt")); /* hash forged file */ - assert_true(pgp_hash_create(&hash_forged, halg)); + rnp::Hash hash_forged(halg); assert_true( - stream_hash_file(&hash_forged, "data/test_stream_signatures/source_forged.txt")); + stream_hash_file(hash_forged, "data/test_stream_signatures/source_forged.txt")); /* find signing key */ - assert_non_null(key = rnp_key_store_get_key_by_id(pubring, sig.keyid(), NULL)); + assert_non_null(key = rnp_key_store_get_signer_key(pubring, &sig)); /* validate signature and fields */ - assert_true(pgp_hash_copy(&hash, &hash_orig)); + rnp::Hash hash; + hash = hash_orig; assert_int_equal(sig.creation(), 1522241943); - assert_rnp_success(signature_validate(&sig, &key->material(), &hash)); + assert_rnp_success(signature_validate(sig, key->material(), hash, global_ctx)); /* check forged file */ - assert_true(pgp_hash_copy(&hash, &hash_forged)); - assert_rnp_failure(signature_validate(&sig, &key->material(), &hash)); + hash = hash_forged; + assert_rnp_failure(signature_validate(sig, key->material(), hash, global_ctx)); /* now let's create signature and sign file */ /* load secret key */ - secring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/test_stream_signatures/sec.asc"); + secring = new rnp_key_store_t( + PGP_KEY_STORE_GPG, "data/test_stream_signatures/sec.asc", global_ctx); assert_true(rnp_key_store_load_from_path(secring, NULL)); - assert_non_null(key = rnp_key_store_get_key_by_id(secring, sig.keyid(), NULL)); + assert_non_null(key = rnp_key_store_get_signer_key(secring, &sig)); assert_true(key->is_secret()); /* fill signature */ uint32_t create = time(NULL); @@ -394,30 +386,37 @@ sig.set_keyid(key->keyid()); sig.set_creation(create); sig.set_expiration(expire); - assert_true(signature_fill_hashed_data(&sig)); + /* make use of add_notation() to cover it */ + try { + std::vector value; + value.resize(66000); + sig.add_notation("dummy@example.com", value, false, true); + assert_true(false); + } catch (const rnp::rnp_exception &e) { + assert_int_equal(e.code(), RNP_ERROR_BAD_PARAMETERS); + } + sig.add_notation("dummy@example.com", "make codecov happy!", false); + sig.fill_hashed_data(); /* try to sign without decrypting of the secret key */ - assert_true(pgp_hash_copy(&hash, &hash_orig)); - assert_rnp_failure(signature_calculate(&sig, &key->material(), &hash, &rng)); + hash = hash_orig; + assert_throw(signature_calculate(sig, key->material(), hash, global_ctx)); /* now unlock the key and sign */ pgp_password_provider_t pswd_prov = {.callback = rnp_password_provider_string, .userdata = (void *) "password"}; assert_true(key->unlock(pswd_prov)); - assert_true(pgp_hash_copy(&hash, &hash_orig)); - assert_rnp_success(signature_calculate(&sig, &key->material(), &hash, &rng)); + hash = hash_orig; + signature_calculate(sig, key->material(), hash, global_ctx); /* now verify signature */ - assert_true(pgp_hash_copy(&hash, &hash_orig)); + hash = hash_orig; /* validate signature and fields */ assert_int_equal(sig.creation(), create); assert_int_equal(sig.expiration(), expire); assert_true(sig.has_subpkt(PGP_SIG_SUBPKT_ISSUER_FPR)); assert_true(sig.keyfp() == key->fp()); - assert_rnp_success(signature_validate(&sig, &key->material(), &hash)); + assert_rnp_success(signature_validate(sig, key->material(), hash, global_ctx)); /* cleanup */ delete pubring; delete secring; - pgp_hash_finish(&hash_orig, NULL); - pgp_hash_finish(&hash_forged, NULL); - rng_destroy(&rng); } TEST_F(rnp_tests, test_stream_signatures_revoked_key) @@ -925,10 +924,6 @@ size_t keylen; pgp_key_sequence_t keyseq; pgp_key_sequence_t keyseq2; - rng_t rng; - - /* we need rng for key encryption */ - assert_true(rng_init(&rng, RNG_SYSTEM)); /* load and decrypt secret keyring, then re-encrypt and reload keys */ assert_rnp_success(init_file_src(&keysrc, "data/keyrings/1/secring.gpg")); @@ -943,10 +938,10 @@ /* change password and encryption algorithm */ key.key.sec_protection.symm_alg = PGP_SA_CAMELLIA_192; - assert_rnp_success(encrypt_secret_key(&key.key, "passw0rd", &rng)); + assert_rnp_success(encrypt_secret_key(&key.key, "passw0rd", global_ctx.rng)); for (auto &subkey : key.subkeys) { subkey.subkey.sec_protection.symm_alg = PGP_SA_CAMELLIA_256; - assert_rnp_success(encrypt_secret_key(&subkey.subkey, "passw0rd", &rng)); + assert_rnp_success(encrypt_secret_key(&subkey.subkey, "passw0rd", global_ctx.rng)); } /* write changed key */ assert_rnp_success(init_mem_dest(&keydst, keybuf, sizeof(keybuf))); @@ -968,10 +963,10 @@ } /* write key without the password */ key2.key.sec_protection.s2k.usage = PGP_S2KU_NONE; - assert_rnp_success(encrypt_secret_key(&key2.key, NULL, NULL)); + assert_rnp_success(encrypt_secret_key(&key2.key, NULL, global_ctx.rng)); for (auto &subkey : key2.subkeys) { subkey.subkey.sec_protection.s2k.usage = PGP_S2KU_NONE; - assert_rnp_success(encrypt_secret_key(&subkey.subkey, NULL, NULL)); + assert_rnp_success(encrypt_secret_key(&subkey.subkey, NULL, global_ctx.rng)); } /* write changed key */ assert_rnp_success(init_mem_dest(&keydst, keybuf, sizeof(keybuf))); @@ -992,47 +987,50 @@ assert_rnp_success(decrypt_secret_key(&subkey.subkey, NULL)); } } - rng_destroy(&rng); } TEST_F(rnp_tests, test_stream_key_signatures) { - rnp_key_store_t * pubring; - pgp_source_t keysrc = {0}; - pgp_key_sequence_t keyseq; - pgp_transferable_key_t * key = NULL; - pgp_transferable_userid_t *uid = NULL; - rng_t rng; - pgp_signature_t * sig; - pgp_key_t * pkey = NULL; - pgp_hash_t hash; - pgp_signature_info_t sinfo = {}; - - /* we need rng for key validation */ - assert_true(rng_init(&rng, RNG_SYSTEM)); + pgp_source_t keysrc = {0}; + pgp_key_sequence_t keyseq; + pgp_key_t * pkey = NULL; + pgp_signature_info_t sinfo = {}; /* v3 public key */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc"); + auto pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_rnp_success(init_file_src(&keysrc, "data/keyrings/4/rsav3-p.asc")); assert_rnp_success(process_pgp_keys(&keysrc, keyseq, false)); src_close(&keysrc); assert_int_equal(keyseq.keys.size(), 1); - assert_non_null(key = &keyseq.keys.front()); - assert_non_null(uid = &key->userids.front()); - assert_non_null(sig = &uid->signatures.front()); - assert_non_null(pkey = rnp_key_store_get_key_by_id(pubring, sig->keyid(), NULL)); + auto &key = keyseq.keys.front(); + auto &uid = key.userids.front(); + auto &sig = uid.signatures.front(); + assert_non_null(pkey = rnp_key_store_get_signer_key(pubring, &sig)); /* check certification signature */ - assert_true(signature_hash_certification(sig, &key->key, &uid->uid, &hash)); - assert_rnp_success(signature_validate(sig, &pkey->material(), &hash)); + rnp::Hash hash; + signature_hash_certification(sig, key.key, uid.uid, hash); + /* this signature uses MD5 hash after the allowed date */ + assert_int_equal(signature_validate(sig, pkey->material(), hash, global_ctx), + RNP_ERROR_SIGNATURE_INVALID); + /* add rule which allows MD5 */ + rnp::SecurityRule allow_md5( + rnp::FeatureType::Hash, PGP_HASH_MD5, rnp::SecurityLevel::Default); + allow_md5.override = true; + global_ctx.profile.add_rule(allow_md5); + assert_rnp_success(signature_validate(sig, pkey->material(), hash, global_ctx)); /* modify userid and check signature */ - uid->uid.uid[2] = '?'; - assert_true(signature_hash_certification(sig, &key->key, &uid->uid, &hash)); - assert_rnp_failure(signature_validate(sig, &pkey->material(), &hash)); + uid.uid.uid[2] = '?'; + signature_hash_certification(sig, key.key, uid.uid, hash); + assert_rnp_failure(signature_validate(sig, pkey->material(), hash, global_ctx)); + /* remove MD5 rule */ + assert_true(global_ctx.profile.del_rule(allow_md5)); delete pubring; /* keyring */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_rnp_success(init_file_src(&keysrc, "data/keyrings/1/pubring.gpg")); assert_rnp_success(process_pgp_keys(&keysrc, keyseq, false)); @@ -1040,79 +1038,96 @@ /* check key signatures */ for (auto &keyref : keyseq.keys) { - key = &keyref; - - for (auto &uid : key->userids) { + for (auto &uid : keyref.userids) { /* userid certifications */ for (auto &sig : uid.signatures) { - assert_non_null(pkey = - rnp_key_store_get_key_by_id(pubring, sig.keyid(), NULL)); + assert_non_null(pkey = rnp_key_store_get_signer_key(pubring, &sig)); /* high level interface */ sinfo.sig = &sig; - sinfo.signer = pkey; - assert_rnp_success(signature_check_certification(&sinfo, &key->key, &uid.uid)); + pkey->validate_cert(sinfo, keyref.key, uid.uid, global_ctx); + assert_true(sinfo.valid); /* low level check */ - assert_true(signature_hash_certification(&sig, &key->key, &uid.uid, &hash)); - assert_rnp_success(signature_validate(&sig, &pkey->material(), &hash)); + signature_hash_certification(sig, keyref.key, uid.uid, hash); + assert_rnp_success( + signature_validate(sig, pkey->material(), hash, global_ctx)); /* modify userid and check signature */ uid.uid.uid[2] = '?'; - assert_rnp_failure(signature_check_certification(&sinfo, &key->key, &uid.uid)); - assert_true(signature_hash_certification(&sig, &key->key, &uid.uid, &hash)); - assert_rnp_failure(signature_validate(&sig, &pkey->material(), &hash)); + pkey->validate_cert(sinfo, keyref.key, uid.uid, global_ctx); + assert_false(sinfo.valid); + signature_hash_certification(sig, keyref.key, uid.uid, hash); + assert_rnp_failure( + signature_validate(sig, pkey->material(), hash, global_ctx)); } } /* subkey binding signatures */ - for (auto &subkey : key->subkeys) { - sig = &subkey.signatures.front(); - assert_non_null(sig); - assert_non_null(pkey = rnp_key_store_get_key_by_id(pubring, sig->keyid(), NULL)); + for (auto &subkey : keyref.subkeys) { + auto &sig = subkey.signatures.front(); + assert_non_null(pkey = rnp_key_store_get_signer_key(pubring, &sig)); /* high level interface */ - sinfo.sig = sig; - sinfo.signer = pkey; + sinfo.sig = &sig; pgp_key_id_t subid; assert_rnp_success(pgp_keyid(subid, subkey.subkey)); - pgp_key_t *psub = rnp_key_store_get_key_by_id(pubring, subid, NULL); + char ssubid[PGP_KEY_ID_SIZE * 2 + 1]; + assert_true(rnp::hex_encode(subid.data(), subid.size(), ssubid, sizeof(ssubid))); + pgp_key_t *psub = rnp_tests_get_key_by_id(pubring, ssubid); assert_non_null(psub); - assert_rnp_success(signature_check_binding(&sinfo, &key->key, psub)); + pkey->validate_binding(sinfo, *psub, global_ctx); + assert_true(sinfo.valid); /* low level check */ - assert_true(signature_hash_binding(sig, &key->key, &subkey.subkey, &hash)); - assert_rnp_success(signature_validate(sig, &pkey->material(), &hash)); + signature_hash_binding(sig, keyref.key, subkey.subkey, hash); + pkey->validate_sig(sinfo, hash, global_ctx); + assert_true(sinfo.valid); } } delete pubring; - rng_destroy(&rng); } -static void +static bool validate_key_sigs(const char *path) { - rnp_key_store_t *pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, path); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + rnp_key_store_t *pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, path, global_ctx); + bool valid = rnp_key_store_load_from_path(pubring, NULL); + assert_true(valid); for (auto &key : pubring->keys) { key.validate(*pubring); - assert_true(key.valid()); + valid = valid && key.valid(); } delete pubring; + return valid; } TEST_F(rnp_tests, test_stream_key_signature_validate) { - rnp_key_store_t *pubring; - pgp_key_t * pkey = NULL; - /* v3 public key */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc"); + rnp_key_store_t *pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_int_equal(rnp_key_store_get_key_count(pubring), 1); - pkey = &pubring->keys.front(); - pkey->validate(*pubring); - assert_true(pkey->valid()); + pgp_key_t &pkey = pubring->keys.front(); + pkey.validate(*pubring); + /* MD5 signature is marked as invalid by default */ + assert_false(pkey.valid()); + rnp::SecurityRule allow_md5( + rnp::FeatureType::Hash, PGP_HASH_MD5, rnp::SecurityLevel::Default); + allow_md5.override = true; + /* Allow MD5 */ + global_ctx.profile.add_rule(allow_md5); + /* we need to manually reset signature validity */ + pkey.get_sig(0).validity.reset(); + pkey.revalidate(*pubring); + assert_true(pkey.valid()); + /* Remove MD5 and revalidate */ + assert_true(global_ctx.profile.del_rule(allow_md5)); + pkey.get_sig(0).validity.reset(); + pkey.revalidate(*pubring); + assert_false(pkey.valid()); delete pubring; /* keyring */ - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg"); + pubring = + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_true(rnp_key_store_get_key_count(pubring) > 0); int i = 0; @@ -1129,30 +1144,32 @@ delete pubring; /* misc key files */ - const char *key_files[] = {"data/test_stream_key_load/dsa-eg-pub.asc", - "data/test_stream_key_load/dsa-eg-sec.asc", - "data/test_stream_key_load/ecc-25519-pub.asc", - "data/test_stream_key_load/ecc-25519-sec.asc", - "data/test_stream_key_load/ecc-x25519-pub.asc", - "data/test_stream_key_load/ecc-x25519-sec.asc", - "data/test_stream_key_load/ecc-p256-pub.asc", - "data/test_stream_key_load/ecc-p256-sec.asc", - "data/test_stream_key_load/ecc-p384-pub.asc", - "data/test_stream_key_load/ecc-p384-sec.asc", - "data/test_stream_key_load/ecc-p521-pub.asc", - "data/test_stream_key_load/ecc-p521-sec.asc", - "data/test_stream_key_load/ecc-bp256-pub.asc", - "data/test_stream_key_load/ecc-bp256-sec.asc", - "data/test_stream_key_load/ecc-bp384-pub.asc", - "data/test_stream_key_load/ecc-bp384-sec.asc", - "data/test_stream_key_load/ecc-bp512-pub.asc", - "data/test_stream_key_load/ecc-bp512-sec.asc", - "data/test_stream_key_load/ecc-p256k1-pub.asc", - "data/test_stream_key_load/ecc-p256k1-sec.asc"}; - - for (size_t i = 0; i < sizeof(key_files) / sizeof(char *); i++) { - validate_key_sigs(key_files[i]); - } + assert_true(validate_key_sigs("data/test_stream_key_load/dsa-eg-pub.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/dsa-eg-sec.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-25519-pub.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-25519-sec.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-x25519-pub.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-x25519-sec.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p256-pub.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p256-sec.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p384-pub.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p384-sec.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p521-pub.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p521-sec.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-bp256-pub.asc") == + brainpool_enabled()); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-bp256-sec.asc") == + brainpool_enabled()); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-bp384-pub.asc") == + brainpool_enabled()); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-bp384-sec.asc") == + brainpool_enabled()); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-bp512-pub.asc") == + brainpool_enabled()); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-bp512-sec.asc") == + brainpool_enabled()); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p256k1-pub.asc")); + assert_true(validate_key_sigs("data/test_stream_key_load/ecc-p256k1-sec.asc")); } TEST_F(rnp_tests, test_stream_verify_no_key) @@ -1165,9 +1182,9 @@ cfg.set_str(CFG_KR_SEC_PATH, ""); cfg.set_str(CFG_KR_PUB_FORMAT, RNP_KEYSTORE_GPG); cfg.set_str(CFG_KR_SEC_FORMAT, RNP_KEYSTORE_GPG); - assert_true(cli_rnp_init(&rnp, cfg)); + assert_true(rnp.init(cfg)); - rnp_cfg &rnpcfg = cli_rnp_cfg(rnp); + rnp_cfg &rnpcfg = rnp.cfg(); /* setup cfg for verification */ rnpcfg.set_str(CFG_INFILE, "data/test_stream_verification/verify_encrypted_no_key.pgp"); rnpcfg.set_str(CFG_OUTFILE, "output.dat"); @@ -1175,10 +1192,16 @@ /* setup operation context */ assert_rnp_success( rnp_ffi_set_pass_provider(rnp.ffi, ffi_string_password_provider, (void *) "pass1")); - /* operation should success if output is not discarded, i.e. operation = decrypt */ rnpcfg.set_bool(CFG_NO_OUTPUT, false); - assert_true(cli_rnp_process_file(&rnp)); - assert_int_equal(file_size("output.dat"), 4); + if (sm2_enabled()) { + /* operation should success if output is not discarded, i.e. operation = decrypt */ + assert_true(cli_rnp_process_file(&rnp)); + assert_int_equal(file_size("output.dat"), 4); + } else { + /* operation should fail */ + assert_false(cli_rnp_process_file(&rnp)); + assert_int_equal(file_size("output.dat"), -1); + } /* try second password */ assert_rnp_success( rnp_ffi_set_pass_provider(rnp.ffi, ffi_string_password_provider, (void *) "pass2")); @@ -1200,7 +1223,7 @@ assert_int_equal(file_size("output.dat"), -1); /* cleanup */ - cli_rnp_end(&rnp); + rnp.end(); } static bool @@ -1268,16 +1291,16 @@ cfg.set_str(CFG_KR_PUB_FORMAT, RNP_KEYSTORE_GPG); cfg.set_str(CFG_KR_SEC_FORMAT, RNP_KEYSTORE_GPG); cfg.set_str(CFG_IO_RESS, "stderr.dat"); - assert_true(cli_rnp_init(&rnp, cfg)); + assert_true(rnp.init(cfg)); - rnp_cfg &rnpcfg = cli_rnp_cfg(rnp); + rnp_cfg &rnpcfg = rnp.cfg(); /* verify */ rnpcfg.set_str(CFG_INFILE, "data/test_messages/future.pgp"); rnpcfg.set_bool(CFG_OVERWRITE, true); assert_true(cli_rnp_process_file(&rnp)); /* clean up and flush the file */ - cli_rnp_end(&rnp); + rnp.end(); /* check the file for presense of correct dates */ auto output = file_to_str("stderr.dat"); @@ -1460,7 +1483,7 @@ rnp_key_store_t *keystore = NULL; pgp_source_t src = {}; - keystore = new rnp_key_store_t(PGP_KEY_STORE_GPG, ""); + keystore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); assert_rnp_success( init_file_src(&src, "data/test_stream_armor/extra_line_before_trailer.asc")); assert_true(rnp_key_store_load_from_src(keystore, &src, NULL)); @@ -1611,7 +1634,7 @@ /* add encryption layers */ for (int i = 0; i < encr; i++) { assert_rnp_success(init_mem_dest(&dst, NULL, 0)); - assert_rnp_success(rnp_raw_encrypt_src(src, dst, "password")); + assert_rnp_success(rnp_raw_encrypt_src(src, dst, "password", global_ctx)); src_close(&src); assert_rnp_success(init_mem_src(&src, mem_dest_own_memory(&dst), dst.writeb, true)); dst_close(&dst, false); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/support.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/support.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/support.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/support.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -44,13 +44,12 @@ #include #include #include +#include #ifndef WINSHELLAPI #include #endif -extern rng_t global_rng; - #ifdef _WIN32 int setenv(const char *name, const char *value, int overwrite) @@ -205,17 +204,19 @@ static bool is_tmp_path(const char *path) { - char rlpath[PATH_MAX] = {0}; - char rltmp[PATH_MAX] = {0}; - if (!realpath(path, rlpath)) { - strncpy(rlpath, path, sizeof(rlpath)); - rlpath[sizeof(rlpath) - 1] = '\0'; + char *rlpath = realpath(path, NULL); + if (!rlpath) { + rlpath = strdup(path); } const char *tmp = get_tmp(); - if (!realpath(tmp, rltmp)) { - strncpy(rltmp, tmp, sizeof(rltmp)); - } - return strncmp(rlpath, rltmp, strlen(rltmp)) == 0; + char * rltmp = realpath(tmp, NULL); + if (!rltmp) { + rltmp = strdup(tmp); + } + bool res = rlpath && rltmp && !strncmp(rlpath, rltmp, strlen(rltmp)); + free(rlpath); + free(rltmp); + return res; } /* Recursively remove a directory. @@ -448,15 +449,15 @@ } bool -cmp_keyid(const pgp_key_id_t &id, const char *val) +cmp_keyid(const pgp_key_id_t &id, const std::string &val) { - return bin_eq_hex(id.data(), id.size(), val); + return bin_eq_hex(id.data(), id.size(), val.c_str()); } bool -cmp_keyfp(const pgp_fingerprint_t &fp, const char *val) +cmp_keyfp(const pgp_fingerprint_t &fp, const std::string &val) { - return bin_eq_hex(fp.fingerprint, fp.length, val); + return bin_eq_hex(fp.fingerprint, fp.length, val.c_str()); } int @@ -604,7 +605,7 @@ } /*initialize the basic RNP structure. */ - return cli_rnp_init(rnp, cfg); + return rnp->init(cfg); } void @@ -734,6 +735,15 @@ return str; } +std::string +lowercase(const std::string &str) +{ + std::string res = str; + std::transform( + res.begin(), res.end(), res.begin(), [](unsigned char ch) { return std::tolower(ch); }); + return res; +} + static bool jso_get_field(json_object *obj, json_object **fld, const std::string &name) { @@ -838,7 +848,36 @@ if (binlen > PGP_KEY_ID_SIZE) { return NULL; } - return rnp_key_store_get_key_by_id(keyring, keyid_bin, after); + pgp_key_search_t search = {}; + search.by.keyid = keyid_bin; + search.type = PGP_KEY_SEARCH_KEYID; + return rnp_key_store_search(keyring, &search, after); +} + +pgp_key_t * +rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const std::string &grip) +{ + if (!keyring || grip.empty() || !ishex(grip)) { + return NULL; + } + pgp_key_grip_t grip_bin = {}; + size_t binlen = rnp::hex_decode(grip.c_str(), grip_bin.data(), grip_bin.size()); + if (binlen > PGP_KEY_GRIP_SIZE) { + return NULL; + } + return rnp_tests_get_key_by_grip(keyring, grip_bin); +} + +pgp_key_t * +rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const pgp_key_grip_t &grip) +{ + if (!keyring) { + return NULL; + } + pgp_key_search_t search = {}; + search.by.grip = grip; + search.type = PGP_KEY_SEARCH_GRIP; + return rnp_key_store_search(keyring, &search, NULL); } pgp_key_t * @@ -858,14 +897,14 @@ } pgp_key_t * -rnp_tests_key_search(rnp_key_store_t *keyring, const std::string &keyid) +rnp_tests_key_search(rnp_key_store_t *keyring, const std::string &uid) { - if (!keyring || keyid.empty()) { + if (!keyring || uid.empty()) { return NULL; } pgp_key_search_t srch_userid = {PGP_KEY_SEARCH_USERID}; - strncpy(srch_userid.by.userid, keyid.c_str(), sizeof(srch_userid.by.userid)); + strncpy(srch_userid.by.userid, uid.c_str(), sizeof(srch_userid.by.userid)); srch_userid.by.userid[sizeof(srch_userid.by.userid) - 1] = '\0'; return rnp_key_store_search(keyring, &srch_userid, NULL); } @@ -1015,3 +1054,153 @@ { return import_keys(ffi, data, len, RNP_LOAD_SAVE_SECRET_KEYS); } + +std::vector +export_key(rnp_key_handle_t key, bool armored, bool secret) +{ + uint32_t flags = RNP_KEY_EXPORT_SUBKEYS; + if (armored) { + flags = flags | RNP_KEY_EXPORT_ARMORED; + } + if (secret) { + flags = flags | RNP_KEY_EXPORT_SECRET; + } else { + flags = flags | RNP_KEY_EXPORT_PUBLIC; + } + rnp_output_t output = NULL; + rnp_output_to_memory(&output, 0); + rnp_key_export(key, output, flags); + size_t len = 0; + uint8_t *buf = NULL; + rnp_output_memory_get_buf(output, &buf, &len, false); + std::vector res(buf, buf + len); + rnp_output_destroy(output); + return res; +} + +void +dump_key_stdout(rnp_key_handle_t key, bool secret) +{ + auto pub = export_key(key, true, false); + printf("%.*s", (int) pub.size(), (char *) pub.data()); + if (!secret) { + return; + } + auto sec = export_key(key, true, true); + printf("%.*s", (int) sec.size(), (char *) sec.data()); +} + +bool +check_uid_valid(rnp_key_handle_t key, size_t idx, bool valid) +{ + rnp_uid_handle_t uid = NULL; + if (rnp_key_get_uid_handle_at(key, idx, &uid)) { + return false; + } + bool val = !valid; + rnp_uid_is_valid(uid, &val); + rnp_uid_handle_destroy(uid); + return val == valid; +} + +bool +check_uid_primary(rnp_key_handle_t key, size_t idx, bool primary) +{ + rnp_uid_handle_t uid = NULL; + if (rnp_key_get_uid_handle_at(key, idx, &uid)) { + return false; + } + bool prim = !primary; + rnp_uid_is_primary(uid, &prim); + rnp_uid_handle_destroy(uid); + return prim == primary; +} + +bool +check_key_valid(rnp_key_handle_t key, bool validity) +{ + bool valid = !validity; + if (rnp_key_is_valid(key, &valid)) { + return false; + } + return valid == validity; +} + +uint32_t +get_key_expiry(rnp_key_handle_t key) +{ + uint32_t expiry = (uint32_t) -1; + rnp_key_get_expiration(key, &expiry); + return expiry; +} + +size_t +get_key_uids(rnp_key_handle_t key) +{ + size_t count = (size_t) -1; + rnp_key_get_uid_count(key, &count); + return count; +} + +bool +check_sub_valid(rnp_key_handle_t key, size_t idx, bool validity) +{ + rnp_key_handle_t sub = NULL; + if (rnp_key_get_subkey_at(key, idx, &sub)) { + return false; + } + bool valid = !validity; + rnp_key_is_valid(sub, &valid); + rnp_key_handle_destroy(sub); + return valid == validity; +} + +bool +sm2_enabled() +{ + bool enabled = false; + if (rnp_supports_feature(RNP_FEATURE_PK_ALG, "SM2", &enabled)) { + return false; + } + return enabled; +} + +bool +aead_eax_enabled() +{ + bool enabled = false; + if (rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "EAX", &enabled)) { + return false; + } + return enabled; +} + +bool +aead_ocb_enabled() +{ + bool enabled = false; + if (rnp_supports_feature(RNP_FEATURE_AEAD_ALG, "OCB", &enabled)) { + return false; + } + return enabled; +} + +bool +twofish_enabled() +{ + bool enabled = false; + if (rnp_supports_feature(RNP_FEATURE_SYMM_ALG, "Twofish", &enabled)) { + return false; + } + return enabled; +} + +bool +brainpool_enabled() +{ + bool enabled = false; + if (rnp_supports_feature(RNP_FEATURE_CURVE, "brainpoolP256r1", &enabled)) { + return false; + } + return enabled; +} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/support.h thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/support.h --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/support.h 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/support.h 2022-04-15 07:49:22.000000000 +0000 @@ -69,6 +69,8 @@ #define realpath(N, R) _fullpath((R), (N), _MAX_PATH) #endif +extern rnp::SecurityContext global_ctx; + /* Check if a file is empty * Use with assert_true and rnp_assert_false(rstate, . */ @@ -135,10 +137,10 @@ bool hex2mpi(pgp_mpi_t *val, const char *hex); /* check whether key id is equal to hex string */ -bool cmp_keyid(const pgp_key_id_t &id, const char *val); +bool cmp_keyid(const pgp_key_id_t &id, const std::string &val); /* check whether key fp is equal to hex string */ -bool cmp_keyfp(const pgp_fingerprint_t &fp, const char *val); +bool cmp_keyfp(const pgp_fingerprint_t &fp, const std::string &val); /* */ @@ -211,6 +213,7 @@ std::string fmt(const char *format, ...); std::string strip_eol(const std::string &str); +std::string lowercase(const std::string &str); bool check_json_field_str(json_object * obj, const std::string &field, @@ -221,9 +224,11 @@ pgp_key_t *rnp_tests_get_key_by_id(rnp_key_store_t * keyring, const std::string &keyid, - pgp_key_t * after); + pgp_key_t * after = NULL); pgp_key_t *rnp_tests_get_key_by_fpr(rnp_key_store_t *keyring, const std::string &keyid); -pgp_key_t *rnp_tests_key_search(rnp_key_store_t *keyring, const std::string &keyid); +pgp_key_t *rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const std::string &grip); +pgp_key_t *rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const pgp_key_grip_t &grip); +pgp_key_t *rnp_tests_key_search(rnp_key_store_t *keyring, const std::string &uid); /* key load/reload shortcuts */ void reload_pubring(rnp_ffi_t *ffi); @@ -238,5 +243,34 @@ bool import_all_keys(rnp_ffi_t ffi, const uint8_t *data, size_t len); bool import_pub_keys(rnp_ffi_t ffi, const uint8_t *data, size_t len); bool import_sec_keys(rnp_ffi_t ffi, const uint8_t *data, size_t len); +/* key export shortcut */ +std::vector export_key(rnp_key_handle_t key, + bool armored = false, + bool secret = false); +/* Dump key to the stdout. Not used in real tests, but useful for artefact generation */ +void dump_key_stdout(rnp_key_handle_t key, bool secret = false); + +/* some shortcuts for less code */ +bool check_key_valid(rnp_key_handle_t key, bool validity); +uint32_t get_key_expiry(rnp_key_handle_t key); +size_t get_key_uids(rnp_key_handle_t key); +bool check_sub_valid(rnp_key_handle_t key, size_t idx, bool validity); +bool check_uid_valid(rnp_key_handle_t key, size_t idx, bool valid); +bool check_uid_primary(rnp_key_handle_t key, size_t idx, bool primary); + +bool sm2_enabled(); +bool aead_eax_enabled(); +bool aead_ocb_enabled(); +bool twofish_enabled(); +bool brainpool_enabled(); + +inline size_t +rnp_round_up(size_t n, size_t align_to) +{ + if (n % align_to) { + n += align_to - (n % align_to); + } + return n; +} #endif /* SUPPORT_H_ */ diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/user-prefs.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/user-prefs.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/user-prefs.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/user-prefs.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -57,7 +57,7 @@ TEST_F(rnp_tests, test_load_user_prefs) { rnp_key_store_t *pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg"); + new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); assert_true(rnp_key_store_load_from_path(pubring, NULL)); assert_int_equal(rnp_key_store_get_key_count(pubring), 7); diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/utils-list.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/utils-list.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/utils-list.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/utils-list.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2017-2019 [Ribose Inc](https://www.ribose.com). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "rnp_tests.h" -#include "support.h" -#include "list.h" - -static void -validate_int_list(list l, const int *expected, size_t count) -{ - list_item *item = list_front(l); - - // check front and back - assert_int_equal(*(int *) list_front(l), expected[0]); - assert_int_equal(*(int *) list_back(l), expected[count - 1]); - - // check length - assert_int_equal(list_length(l), count); - // check list_at - for (size_t i = 0; i < count; i++) { - int *value = (int *) list_at(l, i); - assert_int_equal(*value, expected[i]); - } - // iterate through list - size_t length = 0; - while (item) { - int *value = (int *) item; - // check each value - assert_int_equal(*value, *expected++); - item = list_next(item); - length++; - } - assert_int_equal(list_length(l), length); -} - -TEST_F(rnp_tests, test_utils_list) -{ - list l = NULL; - assert_int_equal(0, list_length(l)); - - // initial append - { - int i = 3; - list_item *item = list_append(&l, &i, sizeof(i)); - assert_int_equal(item, list_back(l)); - assert_int_equal(*(int *) item, i); - static const int expected[] = {3}; - assert_non_null(l); - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // append a few more - { - for (int i = 4; i < 9; i++) { - list_item *item = list_append(&l, &i, sizeof(i)); - assert_int_equal(item, list_back(l)); - assert_int_equal(*(int *) item, i); - } - static const int expected[] = {3, 4, 5, 6, 7, 8}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // insert at front - { - int i = 1; - list_item *item = list_insert(&l, &i, sizeof(i)); - assert_int_equal(item, list_front(l)); - assert_int_equal(*(int *) item, i); - static const int expected[] = {1, 3, 4, 5, 6, 7, 8}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // insert before (front) - { - int i = 0; - list_item *where = list_front(l); - list_item *item = list_insert_before(where, &i, sizeof(i)); - assert_int_equal(item, list_front(l)); - assert_int_equal(*(int *) item, i); - static const int expected[] = {0, 1, 3, 4, 5, 6, 7, 8}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // insert before - { - int i = 2; - list_item *where = list_next(list_next(list_front(l))); - list_item *item = list_insert_before(where, &i, sizeof(i)); - assert_int_equal(list_prev(where), item); - assert_int_equal(list_next(item), where); - assert_int_equal(*(int *) item, i); - static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // append (NULL data) - { - list_item *item = list_append(&l, NULL, sizeof(int)); - assert_int_equal(item, list_back(l)); - assert_non_null(item); - assert_int_equal(*(int *) item, 0); - *(int *) item = 10; - static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // insert after - { - int i = 9; - list_item *where = list_prev(list_back(l)); - list_item *item = list_insert_after(where, &i, sizeof(i)); - assert_int_equal(list_next(where), item); - static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // insert after (end) - { - int i = 11; - list_item *where = list_back(l); - list_item *item = list_insert_after(where, &i, sizeof(i)); - assert_int_equal(item, list_back(l)); - static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // find - { - static const int expected_list[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; - for (size_t i = 0; i < ARRAY_SIZE(expected_list); i++) { - const int *expected = &expected_list[i]; - assert_non_null(list_find(l, expected, sizeof(int))); - assert_int_equal(*(int *) list_find(l, expected, sizeof(int)), *expected); - } - } - - // remove (back) - { - list_remove(list_back(l)); - static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // remove (front) - { - list_remove(list_front(l)); - static const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // find (not found) - { - int i = 0; - assert_null(list_find(l, &i, sizeof(i))); - } - - // insert a duplicate - { - int i = 5; - list_insert_before(list_find(l, &i, sizeof(i)), &i, sizeof(i)); - static const int expected[] = {1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // find the two 5s - { - int i = 5; - list_item *first = list_find(l, &i, sizeof(i)); - assert_non_null(first); - assert_int_equal(*(int *) first, i); - list_item *second = list_find_next(first, &i, sizeof(i)); - assert_non_null(second); - assert_int_equal(*(int *) second, i); - assert_int_not_equal(first, second); - - assert_null(list_find_next(second, &i, sizeof(i))); - - // remove both - list_remove(first); - list_remove(second); - } - - // check the final result - { - static const int expected[] = {1, 2, 3, 4, 6, 7, 8, 9, 10}; - validate_int_list(l, expected, ARRAY_SIZE(expected)); - } - - // check membership - { - list_item *item = list_front(l); - list list2 = NULL; - int i = 1; - assert_true(list_append(&list2, &i, sizeof(i))); - while (item) { - assert_true(list_is_member(l, item)); - assert_false(list_is_member(l, list_front(list2))); - assert_false(list_is_member(list2, item)); - item = list_next(item); - } - list_destroy(&list2); - } - - // list_at edge cases - assert_null(list_at(NULL, 0)); - assert_null(list_at(NULL, 1)); - assert_null(list_at(l, 0xffffff)); - assert_null(list_at(l, list_length(l))); - - // remove all - { - list_item *item = list_front(l); - while (item) { - list_item *next = list_next(item); - list_remove(item); - item = next; - } - assert_null(list_front(l)); - assert_null(list_back(l)); - assert_int_equal(list_length(l), 0); - } - - list_destroy(&l); - assert_null(l); -} diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/utils-rnpcfg.cpp thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/utils-rnpcfg.cpp --- thunderbird-91.7.0+build2/comm/third_party/rnp/src/tests/utils-rnpcfg.cpp 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/src/tests/utils-rnpcfg.cpp 2022-04-15 07:49:22.000000000 +0000 @@ -122,25 +122,44 @@ timeinfo->tm_min = 0; timeinfo->tm_sec = 0; rawtime = mktime(timeinfo); - auto exp = - fmt("%d-%02d-%02d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday); + auto year = timeinfo->tm_year + 1900; + auto mon = timeinfo->tm_mon + 1; + auto day = timeinfo->tm_mday; + rnp_cfg cfg; + cfg.set_str("expiry-", fmt("%d-%02d-%02d", year, mon, day)); + cfg.set_str("expiry/", fmt("%d/%02d/%02d", year, mon, day)); + cfg.set_str("expiry.", fmt("%d.%02d.%02d", year, mon, day)); + uint32_t raw_expiry = 0; - assert_int_equal(get_expiration(exp.c_str(), &raw_expiry), 0); + assert_true(cfg.get_expiration("expiry-", raw_expiry)); assert_int_equal(raw_expiry, rawtime - basetime); - assert_int_equal(get_expiration("2100-01-01", &raw_expiry), 0); - assert_int_equal(get_expiration("2024-02-29", &raw_expiry), 0); + assert_true(cfg.get_expiration("expiry/", raw_expiry)); + assert_int_equal(raw_expiry, rawtime - basetime); + assert_true(cfg.get_expiration("expiry.", raw_expiry)); + assert_int_equal(raw_expiry, rawtime - basetime); + cfg.set_str("expiry", "2100-01-01"); + assert_true(cfg.get_expiration("expiry", raw_expiry)); + assert_int_not_equal(raw_expiry, rawtime - basetime); + cfg.set_str("expiry", "2124-02-29"); + assert_true(cfg.get_expiration("expiry", raw_expiry)); /* date in a past */ - assert_int_not_equal(get_expiration("2000-02-29", &raw_expiry), 0); + cfg.set_str("expiry", "2000-02-29"); + assert_false(cfg.get_expiration("expiry", raw_expiry)); + cfg.set_str("expiry", "2400-02-29"); if ((sizeof(time_t) > 4)) { /* date is correct, but overflows 32 bits */ - assert_int_not_equal(get_expiration("2400-02-29", &raw_expiry), 0); + assert_false(cfg.get_expiration("expiry", raw_expiry)); } else { /* for 32-bit time_t we return INT32_MAX for all dates beyond the y2038 */ - assert_int_equal(get_expiration("2400-02-29", &raw_expiry), 0); + assert_true(cfg.get_expiration("expiry", raw_expiry)); assert_int_equal(raw_expiry, INT32_MAX - basetime); } - assert_int_not_equal(get_expiration("2100-02-29", &raw_expiry), 0); - assert_int_not_equal(get_expiration("4294967296", &raw_expiry), 0); - assert_int_not_equal(get_expiration("2037-02-29", &raw_expiry), 0); - assert_int_not_equal(get_expiration("2037-13-01", &raw_expiry), 0); + cfg.set_str("expiry", "2100-02-29"); + assert_false(cfg.get_expiration("expiry", raw_expiry)); + cfg.set_str("expiry", "4294967296"); + assert_false(cfg.get_expiration("expiry", raw_expiry)); + cfg.set_str("expiry", "2037-02-29"); + assert_false(cfg.get_expiration("expiry", raw_expiry)); + cfg.set_str("expiry", "2037-13-01"); + assert_false(cfg.get_expiration("expiry", raw_expiry)); } diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnp/version.txt thunderbird-91.8.1+build1/comm/third_party/rnp/version.txt --- thunderbird-91.7.0+build2/comm/third_party/rnp/version.txt 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnp/version.txt 2022-04-15 07:49:22.000000000 +0000 @@ -1 +1 @@ -0.15.2 +0.16.0 diff -Nru thunderbird-91.7.0+build2/comm/third_party/rnpdefs.mozbuild thunderbird-91.8.1+build1/comm/third_party/rnpdefs.mozbuild --- thunderbird-91.7.0+build2/comm/third_party/rnpdefs.mozbuild 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/rnpdefs.mozbuild 2022-04-15 07:49:22.000000000 +0000 @@ -18,6 +18,13 @@ COMPILE_FLAGS["OS_INCLUDES"] = [] COMPILE_FLAGS["CLANG_PLUGIN"] = [] +DEFINES["RNP_NO_DEPRECATED"] = True +DEFINES["CRYPTO_BACKEND_BOTAN"] = True +DEFINES["ENABLE_AEAD"] = True +DEFINES["ENABLE_TWOFISH"] = True +DEFINES["ENABLE_BRAINPOOL"] = True + + if CONFIG["COMPILE_ENVIRONMENT"]: COMPILE_FLAGS["MOZ_HARDENING_CFLAGS"] = [] diff -Nru thunderbird-91.7.0+build2/comm/third_party/update_rnp.sh thunderbird-91.8.1+build1/comm/third_party/update_rnp.sh --- thunderbird-91.7.0+build2/comm/third_party/update_rnp.sh 2022-03-07 21:35:20.000000000 +0000 +++ thunderbird-91.8.1+build1/comm/third_party/update_rnp.sh 2022-04-15 07:49:22.000000000 +0000 @@ -26,6 +26,7 @@ if [[ -n "$1" ]]; then CHECKOUT_REV="$1" fi +export PYTHONPATH="../python/thirdroc/" THIRDROC="../../mach python -m thirdroc" MY_TEMP_DIR=$(mktemp -d -t rnp_update.XXXXXX) || exit 1 diff -Nru thunderbird-91.7.0+build2/config/milestone.txt thunderbird-91.8.1+build1/config/milestone.txt --- thunderbird-91.7.0+build2/config/milestone.txt 2022-03-07 21:32:51.000000000 +0000 +++ thunderbird-91.8.1+build1/config/milestone.txt 2022-04-15 07:48:28.000000000 +0000 @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -91.7.0 +91.8.0 diff -Nru thunderbird-91.7.0+build2/debian/changelog thunderbird-91.8.1+build1/debian/changelog --- thunderbird-91.7.0+build2/debian/changelog 2022-03-07 22:18:40.000000000 +0000 +++ thunderbird-91.8.1+build1/debian/changelog 2022-04-15 09:42:35.000000000 +0000 @@ -1,3 +1,21 @@ +thunderbird (1:91.8.1+build1-0ubuntu0.18.04.1) bionic; urgency=medium + + * New upstream stable release (91.8.1build1) + + -- Olivier Tilloy Fri, 15 Apr 2022 11:42:35 +0200 + +thunderbird (1:91.8.0+build2-0ubuntu0.18.04.1) bionic; urgency=medium + + * New upstream stable release (91.8.0build2) + + -- Olivier Tilloy Sat, 02 Apr 2022 22:20:22 +0200 + +thunderbird (1:91.8.0+build1-0ubuntu0.18.04.1) bionic; urgency=medium + + * New upstream stable release (91.8.0build1) + + -- Olivier Tilloy Thu, 31 Mar 2022 08:43:26 +0200 + thunderbird (1:91.7.0+build2-0ubuntu0.18.04.1) bionic; urgency=medium * New upstream stable release (91.7.0build2) diff -Nru thunderbird-91.7.0+build2/docshell/base/BrowsingContext.cpp thunderbird-91.8.1+build1/docshell/base/BrowsingContext.cpp --- thunderbird-91.7.0+build2/docshell/base/BrowsingContext.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/docshell/base/BrowsingContext.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -3424,7 +3424,7 @@ void BrowsingContext::SetActiveSessionHistoryEntry( const Maybe& aPreviousScrollPos, SessionHistoryInfo* aInfo, - uint32_t aLoadType, uint32_t aUpdatedCacheKey) { + uint32_t aLoadType, uint32_t aUpdatedCacheKey, bool aUpdateLength) { if (XRE_IsContentProcess()) { // XXX Why we update cache key only in content process case? if (aUpdatedCacheKey != 0) { @@ -3432,9 +3432,11 @@ } nsID changeID = {}; - RefPtr shistory = Top()->GetChildSessionHistory(); - if (shistory) { - changeID = shistory->AddPendingHistoryChange(); + if (aUpdateLength) { + RefPtr shistory = Top()->GetChildSessionHistory(); + if (shistory) { + changeID = shistory->AddPendingHistoryChange(); + } } ContentChild::GetSingleton()->SendSetActiveSessionHistoryEntry( this, aPreviousScrollPos, *aInfo, aLoadType, aUpdatedCacheKey, diff -Nru thunderbird-91.7.0+build2/docshell/base/BrowsingContext.h thunderbird-91.8.1+build1/docshell/base/BrowsingContext.h --- thunderbird-91.7.0+build2/docshell/base/BrowsingContext.h 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/docshell/base/BrowsingContext.h 2022-04-15 07:40:53.000000000 +0000 @@ -793,7 +793,8 @@ void SetActiveSessionHistoryEntry(const Maybe& aPreviousScrollPos, SessionHistoryInfo* aInfo, uint32_t aLoadType, - uint32_t aUpdatedCacheKey); + uint32_t aUpdatedCacheKey, + bool aUpdateLength = true); // Replace the active entry for this browsing context. This is used for // implementing history.replaceState and same document navigations. diff -Nru thunderbird-91.7.0+build2/docshell/base/CanonicalBrowsingContext.cpp thunderbird-91.8.1+build1/docshell/base/CanonicalBrowsingContext.cpp --- thunderbird-91.7.0+build2/docshell/base/CanonicalBrowsingContext.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/docshell/base/CanonicalBrowsingContext.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -750,6 +750,8 @@ MOZ_LOG(gSHLog, LogLevel::Verbose, ("CanonicalBrowsingContext::SessionHistoryCommit %p %" PRIu64, this, aLoadId)); + MOZ_ASSERT(aLoadId != UINT64_MAX, + "Must not send special about:blank loadinfo to parent."); for (size_t i = 0; i < mLoadingEntries.Length(); ++i) { if (mLoadingEntries[i].mLoadId == aLoadId) { nsSHistory* shistory = static_cast(GetSessionHistory()); diff -Nru thunderbird-91.7.0+build2/docshell/base/nsDocShell.cpp thunderbird-91.8.1+build1/docshell/base/nsDocShell.cpp --- thunderbird-91.7.0+build2/docshell/base/nsDocShell.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/docshell/base/nsDocShell.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -230,6 +230,7 @@ #include "nsWidgetsCID.h" #include "nsXULAppAPI.h" +#include "ThirdPartyUtil.h" #include "BRNameMatchingPolicy.h" #include "GeckoProfiler.h" #include "mozilla/NullPrincipal.h" @@ -388,7 +389,8 @@ mWillChangeProcess(false), mIsNavigating(false), mSuspendMediaWhenInactive(false), - mForcedAutodetection(false) { + mForcedAutodetection(false), + mNeedToReportActiveAfterLoadingBecomesActive(false) { // If no outer window ID was provided, generate a new one. if (aContentWindowID == 0) { mContentWindowID = nsContentUtils::GenerateWindowId(); @@ -8687,6 +8689,7 @@ if (aLoadState->GetLoadingSessionHistoryInfo()) { mLoadingEntry = MakeUnique( *aLoadState->GetLoadingSessionHistoryInfo()); + mNeedToReportActiveAfterLoadingBecomesActive = false; } // Set the doc's URI according to the new history entry's URI. @@ -9899,6 +9902,14 @@ return true; } +bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank( + nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { + return NS_IsAboutBlank(aURI) && aInheritPrincipal && + (aPrincipalToInherit == GetInheritedPrincipal(false)) && + (!mContentViewer || !mContentViewer->GetDocument() || + mContentViewer->GetDocument()->IsInitialDocument()); +} + nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, Maybe aCacheKey, nsIRequest** aRequest) { @@ -10040,11 +10051,44 @@ "DoURILoad thinks this is a document and InternalLoad does not"); } + // We want to inherit aLoadState->PrincipalToInherit() when: + // 1. ChannelShouldInheritPrincipal returns true. + // 2. aLoadState->URI() is not data: URI, or data: URI is not + // configured as unique opaque origin. + bool inheritPrincipal = false; + + if (aLoadState->PrincipalToInherit()) { + bool isSrcdoc = + aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); + bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( + aLoadState->PrincipalToInherit(), aLoadState->URI(), + true, // aInheritForAboutBlank + isSrcdoc); + + inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI()); + } + + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570 + const bool isAboutBlankLoadOntoInitialAboutBlank = + IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal, + aLoadState->PrincipalToInherit()); + // FIXME We still have a ton of codepaths that don't pass through // DocumentLoadListener, so probably need to create session history info // in more places. if (aLoadState->GetLoadingSessionHistoryInfo()) { SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo()); + } else if (isAboutBlankLoadOntoInitialAboutBlank && + mozilla::SessionHistoryInParent()) { + // Materialize LoadingSessionHistoryInfo here, because DocumentChannel + // loads have it, and later history behavior depends on it existing. + UniquePtr entry = MakeUnique( + aLoadState->URI(), aLoadState->TriggeringPrincipal(), + aLoadState->PrincipalToInherit(), + aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(), + mContentTypeHint); + mozilla::dom::LoadingSessionHistoryInfo info(*entry); + SetLoadingSessionHistoryInfo(info, true); } // open a channel for the url @@ -10128,23 +10172,6 @@ return NS_ERROR_FAILURE; } - // We want to inherit aLoadState->PrincipalToInherit() when: - // 1. ChannelShouldInheritPrincipal returns true. - // 2. aLoadState->URI() is not data: URI, or data: URI is not - // configured as unique opaque origin. - bool inheritPrincipal = false; - - if (aLoadState->PrincipalToInherit()) { - bool isSrcdoc = - aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); - bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( - aLoadState->PrincipalToInherit(), aLoadState->URI(), - true, // aInheritForAboutBlank - isSrcdoc); - - inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI()); - } - uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags(); nsSecurityFlags securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; @@ -10177,6 +10204,30 @@ sandboxFlags); RefPtr context = mBrowsingContext->GetCurrentWindowContext(); + if (isAboutBlankLoadOntoInitialAboutBlank) { + // Match the DocumentChannel case where the default for third-partiness + // differs from the default in LoadInfo construction here. + // toolkit/components/antitracking/test/browser/browser_aboutblank.js + // fails without this. + BrowsingContext* top = mBrowsingContext->Top(); + if (top == mBrowsingContext) { + // If we're at the top, this must be a window.open()ed + // window, and we can't be third-party relative to ourselves. + loadInfo->SetIsThirdPartyContextToTopWindow(false); + } else { + if (Document* topDoc = top->GetDocument()) { + bool thirdParty = false; + mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal( + aLoadState->PrincipalToInherit(), &thirdParty); + loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty); + } else { + // If top is in a different process, we have to be third-party relative + // to it. + loadInfo->SetIsThirdPartyContextToTopWindow(true); + } + } + } + if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess() && context->HasValidTransientUserGestureActivation()) { aLoadState->SetHasValidUserGestureActivation(true); @@ -10244,7 +10295,8 @@ currentUnstrippedURI); nsCOMPtr channel; - if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI())) { + if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && + !isAboutBlankLoadOntoInitialAboutBlank) { channel = DocumentChannel::CreateForDocument(aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified, isXFOError); @@ -13308,13 +13360,16 @@ } void nsDocShell::SetLoadingSessionHistoryInfo( - const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo) { + const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, + bool aNeedToReportActiveAfterLoadingBecomesActive) { // FIXME Would like to assert this, but can't yet. // MOZ_ASSERT(!mLoadingEntry); MOZ_LOG(gSHLog, LogLevel::Debug, ("Setting the loading entry on nsDocShell %p to %s", this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get())); mLoadingEntry = MakeUnique(aLoadingInfo); + mNeedToReportActiveAfterLoadingBecomesActive = + aNeedToReportActiveAfterLoadingBecomesActive; } void nsDocShell::MoveLoadingToActiveEntry(bool aPersist) { @@ -13336,16 +13391,25 @@ mActiveEntry = MakeUnique(mLoadingEntry->mInfo); mLoadingEntry.swap(loadingEntry); if (!mActiveEntryIsLoadingFromSessionHistory) { + if (mNeedToReportActiveAfterLoadingBecomesActive) { + // Needed to pass various history length WPTs. + mBrowsingContext->SetActiveSessionHistoryEntry( + mozilla::Nothing(), mActiveEntry.get(), mLoadType, + /* aUpdatedCacheKey = */ 0, false); + } mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); } } + mNeedToReportActiveAfterLoadingBecomesActive = false; if (mActiveEntry) { MOZ_ASSERT(loadingEntry); uint32_t loadType = mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType; - mBrowsingContext->SessionHistoryCommit(*loadingEntry, loadType, - hadActiveEntry, aPersist, false); + if (loadingEntry->mLoadId != UINT64_MAX) { + mBrowsingContext->SessionHistoryCommit(*loadingEntry, loadType, + hadActiveEntry, aPersist, false); + } } } diff -Nru thunderbird-91.7.0+build2/docshell/base/nsDocShell.h thunderbird-91.8.1+build1/docshell/base/nsDocShell.h --- thunderbird-91.7.0+build2/docshell/base/nsDocShell.h 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/docshell/base/nsDocShell.h 2022-04-15 07:40:53.000000000 +0000 @@ -493,7 +493,8 @@ mozilla::dom::BrowsingContext* aBrowsingContext, uint32_t aLoadType); void SetLoadingSessionHistoryInfo( - const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo); + const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, + bool aNeedToReportActiveAfterLoadingBecomesActive = false); const mozilla::dom::LoadingSessionHistoryInfo* GetLoadingSessionHistoryInfo() { return mLoadingEntry.get(); @@ -666,6 +667,12 @@ nsIURI* aCurrentURI, nsIReferrerInfo* aReferrerInfo, bool aNotifiedBeforeUnloadListeners = false); + public: + bool IsAboutBlankLoadOntoInitialAboutBlank(nsIURI* aURI, + bool aInheritPrincipal, + nsIPrincipal* aPrincipalToInherit); + + private: // // URI Load // @@ -1167,7 +1174,9 @@ // These are only set when fission.sessionHistoryInParent is set. mozilla::UniquePtr mActiveEntry; bool mActiveEntryIsLoadingFromSessionHistory = false; - // mLoadingEntry is set when we're about to start loading. + // mLoadingEntry is set when we're about to start loading. Whenever + // setting mLoadingEntry, be sure to also set + // mNeedToReportActiveAfterLoadingBecomesActive. mozilla::UniquePtr mLoadingEntry; // Holds a weak pointer to a RestorePresentationEvent object if any that @@ -1309,6 +1318,12 @@ // Whether we have a pending encoding autodetection request from the // menu for all encodings. bool mForcedAutodetection : 1; + + // Whether mBrowsingContext->SetActiveSessionHistoryEntry() needs to be called + // when the loading entry becomes the active entry. This is used for the + // initial about:blank-replacing about:blank in order to make the history + // length WPTs pass. + bool mNeedToReportActiveAfterLoadingBecomesActive : 1; }; #endif /* nsDocShell_h__ */ diff -Nru thunderbird-91.7.0+build2/docshell/shistory/SessionHistoryEntry.cpp thunderbird-91.8.1+build1/docshell/shistory/SessionHistoryEntry.cpp --- thunderbird-91.7.0+build2/docshell/shistory/SessionHistoryEntry.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/docshell/shistory/SessionHistoryEntry.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -355,6 +355,10 @@ SessionHistoryEntry::sLoadIdToEntry->Get(mLoadId) == aEntry); } +LoadingSessionHistoryInfo::LoadingSessionHistoryInfo( + const SessionHistoryInfo& aInfo) + : mInfo(aInfo), mLoadId(UINT64_MAX) {} + already_AddRefed LoadingSessionHistoryInfo::CreateLoadInfo() const { RefPtr loadState( @@ -1195,7 +1199,7 @@ // This should ideally stop being an issue once the Fission-aware // session history rewrite is complete. NS_ASSERTION( - aUseRemoteSubframes, + aUseRemoteSubframes || NS_IsAboutBlank(oldChild->Info().GetURI()), "Adding a child where we already have a child? This may misbehave"); oldChild->SetParent(nullptr); } diff -Nru thunderbird-91.7.0+build2/docshell/shistory/SessionHistoryEntry.h thunderbird-91.8.1+build1/docshell/shistory/SessionHistoryEntry.h --- thunderbird-91.7.0+build2/docshell/shistory/SessionHistoryEntry.h 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/docshell/shistory/SessionHistoryEntry.h 2022-04-15 07:40:53.000000000 +0000 @@ -217,6 +217,9 @@ LoadingSessionHistoryInfo(SessionHistoryEntry* aEntry, LoadingSessionHistoryInfo* aInfo); + // For about:blank only. + explicit LoadingSessionHistoryInfo(const SessionHistoryInfo& aInfo); + already_AddRefed CreateLoadInfo() const; SessionHistoryInfo mInfo; diff -Nru thunderbird-91.7.0+build2/dom/base/Document.cpp thunderbird-91.8.1+build1/dom/base/Document.cpp --- thunderbird-91.7.0+build2/dom/base/Document.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/base/Document.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -4178,8 +4178,13 @@ mDocumentL10n->AddResourceId(href); if (mReadyState >= READYSTATE_INTERACTIVE) { - mDocumentL10n->Activate(true); - mDocumentL10n->TriggerInitialTranslation(); + RefPtr l10n = mDocumentL10n; + RefPtr r = NS_NewRunnableFunction( + "DocumentL10n::TriggerInitialTranslation()", [l10n]() { + l10n->Activate(true); + l10n->TriggerInitialTranslation(); + }); + nsContentUtils::AddScriptRunner(r.forget()); } else { if (!mDocumentL10n->mBlockingLayout) { // Our initial translation is going to block layout start. Make sure @@ -4235,7 +4240,8 @@ OnL10nResourceContainerParsed(); if (mDocumentL10n) { - mDocumentL10n->TriggerInitialTranslation(); + RefPtr l10n = mDocumentL10n; + l10n->TriggerInitialTranslation(); } } diff -Nru thunderbird-91.7.0+build2/dom/base/nsObjectLoadingContent.cpp thunderbird-91.8.1+build1/dom/base/nsObjectLoadingContent.cpp --- thunderbird-91.7.0+build2/dom/base/nsObjectLoadingContent.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/base/nsObjectLoadingContent.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -1758,6 +1758,15 @@ return NS_OK; } +bool nsObjectLoadingContent::IsAboutBlankLoadOntoInitialAboutBlank( + nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { + return NS_IsAboutBlank(aURI) && aInheritPrincipal && + (!mFrameLoader || !mFrameLoader->GetExistingDocShell() || + mFrameLoader->GetExistingDocShell() + ->IsAboutBlankLoadOntoInitialAboutBlank(aURI, aInheritPrincipal, + aPrincipalToInherit)); +} + nsresult nsObjectLoadingContent::OpenChannel() { nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); @@ -1830,7 +1839,9 @@ loadInfo->SetCSPToInherit(cspToInherit); } - if (DocumentChannel::CanUseDocumentChannel(mURI)) { + if (DocumentChannel::CanUseDocumentChannel(mURI) && + !IsAboutBlankLoadOntoInitialAboutBlank(mURI, inheritPrincipal, + thisContent->NodePrincipal())) { // --- Create LoadState RefPtr loadState = new nsDocShellLoadState(mURI); loadState->SetPrincipalToInherit(thisContent->NodePrincipal()); diff -Nru thunderbird-91.7.0+build2/dom/base/nsObjectLoadingContent.h thunderbird-91.8.1+build1/dom/base/nsObjectLoadingContent.h --- thunderbird-91.7.0+build2/dom/base/nsObjectLoadingContent.h 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/base/nsObjectLoadingContent.h 2022-04-15 07:40:53.000000000 +0000 @@ -371,6 +371,12 @@ */ void QueueCheckPluginStopEvent(); + public: + bool IsAboutBlankLoadOntoInitialAboutBlank(nsIURI* aURI, + bool aInheritPrincipal, + nsIPrincipal* aPrincipalToInherit); + + private: /** * Opens the channel pointed to by mURI into mChannel. */ diff -Nru thunderbird-91.7.0+build2/dom/base/test/test_bug338583.html thunderbird-91.8.1+build1/dom/base/test/test_bug338583.html --- thunderbird-91.7.0+build2/dom/base/test/test_bug338583.html 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/base/test/test_bug338583.html 2022-04-15 07:40:53.000000000 +0000 @@ -338,7 +338,7 @@ } function doTest3_g(test_id) { - gEventSourceObj3_g = new EventSource("http://hdfskjghsbg.jtiyoejowe.dafsgbhjab.com"); + gEventSourceObj3_g = new EventSource("http://hdfskjghsbg.jtiyoejowe.example.com"); gEventSourceObj3_g.onmessage = fn_onmessage; gEventSourceObj3_g.hits = []; diff -Nru thunderbird-91.7.0+build2/dom/canvas/ClientWebGLContext.cpp thunderbird-91.8.1+build1/dom/canvas/ClientWebGLContext.cpp --- thunderbird-91.7.0+build2/dom/canvas/ClientWebGLContext.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/canvas/ClientWebGLContext.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -909,6 +909,7 @@ } const auto& surfSize = res.surfSize; const webgl::RaiiShmem shmem{child, res.shmem}; + if (!shmem) return nullptr; const auto& shmemBytes = shmem.ByteRange(); if (!surfSize.x) return nullptr; // Zero means failure. @@ -1002,7 +1003,7 @@ const auto desc = webgl::ReadPixelsDesc{{0, 0}, size}; const auto range = Range(map.GetData(), stride * size.y); - DoReadPixels(desc, range); + if (!DoReadPixels(desc, range)) return nullptr; const auto begin = range.begin().get(); @@ -3099,6 +3100,10 @@ return; } const webgl::RaiiShmem shmem{child, rawShmem}; + if (!shmem) { + EnqueueError(LOCAL_GL_OUT_OF_MEMORY, "Failed to map in sub data buffer."); + return; + } const auto shmemView = shmem.ByteRange(); MOZ_RELEASE_ASSERT(shmemView.length() == 1 + destView.length()); @@ -4575,18 +4580,20 @@ {format, type}, state.mPixelPackState}; const auto range = Range(bytes, byteLen); - DoReadPixels(desc, range); + if (!DoReadPixels(desc, range)) { + return; + } } -void ClientWebGLContext::DoReadPixels(const webgl::ReadPixelsDesc& desc, +bool ClientWebGLContext::DoReadPixels(const webgl::ReadPixelsDesc& desc, const Range dest) const { const auto notLost = mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. - if (!notLost) return; + if (!notLost) return false; const auto& inProcess = notLost->inProcess; if (inProcess) { inProcess->ReadPixelsInto(desc, dest); - return; + return true; } const auto& child = notLost->outOfProcess; child->FlushPendingCmds(); @@ -4594,16 +4601,20 @@ if (!child->SendReadPixels(desc, dest.length(), &res)) { res = {}; } - if (!res.byteStride) return; + if (!res.byteStride) return false; const auto& byteStride = res.byteStride; const auto& subrect = res.subrect; const webgl::RaiiShmem shmem{child, res.shmem}; const auto& shmemBytes = shmem.ByteRange(); + if (!shmem) { + EnqueueError(LOCAL_GL_OUT_OF_MEMORY, "Failed to map in back buffer."); + return false; + } uint8_t bpp; if (!GetBytesPerPixel(desc.pi, &bpp)) { MOZ_ASSERT(false); - return; + return false; } const auto& packing = desc.packState; @@ -4628,6 +4639,8 @@ } Memcpy(destItr, srcItr, xByteSize); } + + return true; } bool ClientWebGLContext::ReadPixels_SharedPrecheck( diff -Nru thunderbird-91.7.0+build2/dom/canvas/ClientWebGLContext.h thunderbird-91.8.1+build1/dom/canvas/ClientWebGLContext.h --- thunderbird-91.7.0+build2/dom/canvas/ClientWebGLContext.h 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/canvas/ClientWebGLContext.h 2022-04-15 07:40:53.000000000 +0000 @@ -1009,7 +1009,8 @@ private: RefPtr BackBufferSnapshot(); - void DoReadPixels(const webgl::ReadPixelsDesc&, Range) const; + [[nodiscard]] bool DoReadPixels(const webgl::ReadPixelsDesc&, + Range) const; uvec2 DrawingBufferSize(); void AfterDrawCall() { diff -Nru thunderbird-91.7.0+build2/dom/canvas/WebGLContextDraw.cpp thunderbird-91.8.1+build1/dom/canvas/WebGLContextDraw.cpp --- thunderbird-91.7.0+build2/dom/canvas/WebGLContextDraw.cpp 2022-03-07 21:32:53.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/canvas/WebGLContextDraw.cpp 2022-04-15 07:40:53.000000000 +0000 @@ -976,7 +976,17 @@ : WebGLVertexAttrib0Status::EmulatedInitializedArray; } -bool WebGLContext::DoFakeVertexAttrib0(const uint64_t vertexCount) { +bool WebGLContext::DoFakeVertexAttrib0(const uint64_t totalVertCount) { + if (gl->WorkAroundDriverBugs() && gl->IsMesa()) { + // Padded/strided to vec4, so 4x4bytes. + const auto effectiveVertAttribBytes = + CheckedInt(totalVertCount) * 4 * 4; + if (!effectiveVertAttribBytes.isValid()) { + ErrorOutOfMemory("`offset + count` too large for Mesa."); + return false; + } + } + const auto whatDoesAttrib0Need = WhatDoesVertexAttrib0Need(); if (MOZ_LIKELY(whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)) return true; @@ -1019,14 +1029,14 @@ //// const auto bytesPerVert = sizeof(mFakeVertexAttrib0Data); - const auto checked_dataSize = CheckedUint32(vertexCount) * bytesPerVert; + const auto checked_dataSize = CheckedUint32(totalVertCount) * bytesPerVert; if (!checked_dataSize.isValid()) { ErrorOutOfMemory( "Integer overflow trying to construct a fake vertex attrib 0" " array for a draw-operation with %" PRIu64 " vertices. Try" " reducing the number of vertices.", - vertexCount); + totalVertCount); return false; } const auto dataSize = checked_dataSize.value(); diff -Nru thunderbird-91.7.0+build2/dom/fetch/FetchDriver.cpp thunderbird-91.8.1+build1/dom/fetch/FetchDriver.cpp --- thunderbird-91.7.0+build2/dom/fetch/FetchDriver.cpp 2022-03-07 21:32:55.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/fetch/FetchDriver.cpp 2022-04-15 07:40:54.000000000 +0000 @@ -1295,10 +1295,14 @@ } } + if (!mResponse) { + MOZ_ASSERT(false); + return NS_ERROR_UNEXPECTED; + } + // Needs to be initialized to 0 because in some cases nsStringInputStream may // not write to aRead. uint32_t aRead = 0; - MOZ_ASSERT(mResponse); MOZ_ASSERT(mPipeOutputStream); // From "Main Fetch" step 19: SRI-part2. diff -Nru thunderbird-91.7.0+build2/dom/file/ipc/RemoteLazyInputStream.cpp thunderbird-91.8.1+build1/dom/file/ipc/RemoteLazyInputStream.cpp --- thunderbird-91.7.0+build2/dom/file/ipc/RemoteLazyInputStream.cpp 2022-03-07 21:32:55.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/file/ipc/RemoteLazyInputStream.cpp 2022-04-15 07:40:54.000000000 +0000 @@ -281,6 +281,10 @@ RemoteLazyInputStream::Close() { nsCOMPtr asyncRemoteStream; nsCOMPtr remoteStream; + + nsCOMPtr inputStreamCallback; + nsCOMPtr inputStreamCallbackEventTarget; + { MutexAutoLock lock(mMutex); @@ -292,15 +296,22 @@ asyncRemoteStream.swap(mAsyncRemoteStream); remoteStream.swap(mRemoteStream); - mInputStreamCallback = nullptr; - mInputStreamCallbackEventTarget = nullptr; - + // TODO(Bug 1737783): Notify to the mFileMetadataCallback that this + // lazy input stream has been closed. mFileMetadataCallback = nullptr; mFileMetadataCallbackEventTarget = nullptr; + inputStreamCallback = std::move(mInputStreamCallback); + inputStreamCallbackEventTarget = std::move(mInputStreamCallbackEventTarget); + mState = eClosed; } + if (inputStreamCallback) { + InputStreamCallbackRunnable::Execute(inputStreamCallback, + inputStreamCallbackEventTarget, this); + } + if (asyncRemoteStream) { asyncRemoteStream->CloseWithStatus(NS_BASE_STREAM_CLOSED); } diff -Nru thunderbird-91.7.0+build2/dom/l10n/DocumentL10n.cpp thunderbird-91.8.1+build1/dom/l10n/DocumentL10n.cpp --- thunderbird-91.7.0+build2/dom/l10n/DocumentL10n.cpp 2022-03-07 21:32:54.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/l10n/DocumentL10n.cpp 2022-04-15 07:40:55.000000000 +0000 @@ -6,6 +6,7 @@ #include "DocumentL10n.h" #include "nsIContentSink.h" +#include "nsContentUtils.h" #include "mozilla/dom/AutoEntryScript.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/DocumentL10nBinding.h" @@ -102,6 +103,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(L10nReadyHandler) void DocumentL10n::TriggerInitialTranslation() { + MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); if (mState >= DocumentL10nState::InitialTranslationTriggered) { return; } diff -Nru thunderbird-91.7.0+build2/dom/webauthn/WinWebAuthnManager.cpp thunderbird-91.8.1+build1/dom/webauthn/WinWebAuthnManager.cpp --- thunderbird-91.7.0+build2/dom/webauthn/WinWebAuthnManager.cpp 2022-03-07 21:32:56.000000000 +0000 +++ thunderbird-91.8.1+build1/dom/webauthn/WinWebAuthnManager.cpp 2022-04-15 07:40:55.000000000 +0000 @@ -288,10 +288,12 @@ break; } + if (extra.Extensions().Length() > (int)(sizeof(rgExtension) / sizeof(rgExtension[0]))) { + nsresult aError = NS_ERROR_DOM_INVALID_STATE_ERR; + MaybeAbortRegister(aTransactionId, aError); + return; + } for (const WebAuthnExtension& ext : extra.Extensions()) { - MOZ_ASSERT(cExtensions < - (int)(sizeof(rgExtension) / sizeof(rgExtension[0]))); - if (ext.type() == WebAuthnExtension::TWebAuthnExtensionHmacSecret) { HmacCreateSecret = ext.get_WebAuthnExtensionHmacSecret().hmacCreateSecret() == true; diff -Nru thunderbird-91.7.0+build2/editor/libeditor/EditorBase.cpp thunderbird-91.8.1+build1/editor/libeditor/EditorBase.cpp --- thunderbird-91.7.0+build2/editor/libeditor/EditorBase.cpp 2022-03-07 21:32:56.000000000 +0000 +++ thunderbird-91.8.1+build1/editor/libeditor/EditorBase.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -6135,6 +6135,63 @@ "mTopLevelEditSubActionData.mSelectedRange should've been cleared"); } +void EditorBase::AutoEditActionDataSetter::UpdateSelectionCache( + Selection& aSelection) { + MOZ_ASSERT(aSelection.GetType() == SelectionType::eNormal); + + if (mSelection == &aSelection) { + return; + } + + AutoEditActionDataSetter& topLevelEditActionData = + [&]() -> AutoEditActionDataSetter& { + for (AutoEditActionDataSetter* editActionData = this;; + editActionData = editActionData->mParentData) { + if (!editActionData->mParentData) { + return *editActionData; + } + } + MOZ_ASSERT_UNREACHABLE("You do something wrong"); + }(); + + // Keep grabbing the old selection in the top level edit action data until the + // all owners end handling it. + if (mSelection) { + topLevelEditActionData.mRetiredSelections.AppendElement(*mSelection); + } + + // If the old selection is in batch, we should end the batch which + // `EditorBase::BeginUpdateViewBatch` started. + if (mEditorBase.mUpdateCount && mSelection) { + mSelection->EndBatchChanges(); + } + + Selection* previousSelection = mSelection; + mSelection = &aSelection; + for (AutoEditActionDataSetter* parentActionData = mParentData; + parentActionData; parentActionData = parentActionData->mParentData) { + if (!parentActionData->mSelection) { + continue; + } + // Skip scanning mRetiredSelections if we've already handled the selection + // previous time. + if (parentActionData->mSelection != previousSelection) { + if (!topLevelEditActionData.mRetiredSelections.Contains( + OwningNonNull(*parentActionData->mSelection))) { + topLevelEditActionData.mRetiredSelections.AppendElement( + *parentActionData->mSelection); + } + previousSelection = parentActionData->mSelection; + } + parentActionData->mSelection = &aSelection; + } + + // Restart the batching in the new selection. + if (mEditorBase.mUpdateCount) { + aSelection.StartBatchChanges(); + } +} + void EditorBase::AutoEditActionDataSetter::SetColorData( const nsAString& aData) { MOZ_ASSERT(!HasTriedToDispatchBeforeInputEvent(), diff -Nru thunderbird-91.7.0+build2/editor/libeditor/EditorBase.h thunderbird-91.8.1+build1/editor/libeditor/EditorBase.h --- thunderbird-91.7.0+build2/editor/libeditor/EditorBase.h 2022-03-07 21:32:56.000000000 +0000 +++ thunderbird-91.8.1+build1/editor/libeditor/EditorBase.h 2022-04-15 07:40:55.000000000 +0000 @@ -1304,17 +1304,7 @@ return mParentData ? mParentData->RangeUpdaterRef() : mRangeUpdater; } - void UpdateSelectionCache(Selection& aSelection) { - MOZ_ASSERT(aSelection.GetType() == SelectionType::eNormal); - - AutoEditActionDataSetter* actionData = this; - while (actionData) { - if (actionData->mSelection) { - actionData->mSelection = &aSelection; - } - actionData = actionData->mParentData; - } - } + void UpdateSelectionCache(Selection& aSelection); private: bool IsBeforeInputEventEnabled() const; @@ -1378,6 +1368,7 @@ EditorBase& mEditorBase; RefPtr mSelection; + nsTArray> mRetiredSelections; nsCOMPtr mPrincipal; // EditAction may be nested, for example, a command may be executed // from mutation event listener which is run while editor changes diff -Nru thunderbird-91.7.0+build2/gfx/gl/GLContext.cpp thunderbird-91.8.1+build1/gfx/gl/GLContext.cpp --- thunderbird-91.7.0+build2/gfx/gl/GLContext.cpp 2022-03-07 21:32:56.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/gl/GLContext.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -666,11 +666,19 @@ } } + { + const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION); + if (strstr(versionStr, "Mesa")) { + mIsMesa = true; + } + } + if (ShouldSpew()) { printf_stderr("GL_VENDOR: %s\n", glVendorString); printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]); printf_stderr("GL_RENDERER: %s\n", glRendererString); printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]); + printf_stderr("mIsMesa: %i\n", int(mIsMesa)); } //////////////// @@ -732,8 +740,7 @@ MarkUnsupported(GLFeature::framebuffer_multisample); } - const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION); - if (strstr(versionStr, "Mesa")) { + if (IsMesa()) { // DrawElementsInstanced hangs the driver. MarkUnsupported(GLFeature::robust_buffer_access_behavior); } diff -Nru thunderbird-91.7.0+build2/gfx/gl/GLContext.h thunderbird-91.8.1+build1/gfx/gl/GLContext.h --- thunderbird-91.7.0+build2/gfx/gl/GLContext.h 2022-03-07 21:32:56.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/gl/GLContext.h 2022-04-15 07:40:56.000000000 +0000 @@ -280,8 +280,8 @@ } GLVendor Vendor() const { return mVendor; } - GLRenderer Renderer() const { return mRenderer; } + bool IsMesa() const { return mIsMesa; } bool IsContextLost() const { return mContextLost; } @@ -335,6 +335,7 @@ GLVendor mVendor = GLVendor::Other; GLRenderer mRenderer = GLRenderer::Other; + bool mIsMesa = false; // ----------------------------------------------------------------------------- // Extensions management diff -Nru thunderbird-91.7.0+build2/gfx/layers/ipc/ContentCompositorBridgeParent.cpp thunderbird-91.8.1+build1/gfx/layers/ipc/ContentCompositorBridgeParent.cpp --- thunderbird-91.7.0+build2/gfx/layers/ipc/ContentCompositorBridgeParent.cpp 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/layers/ipc/ContentCompositorBridgeParent.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -15,6 +15,7 @@ # include "mozilla/gfx/DeviceManagerDx.h" // for DeviceManagerDx # include "mozilla/layers/ImageDataSerializer.h" #endif +#include "mozilla/StaticPrefs_dom.h" #include "mozilla/dom/WebGLParent.h" #include "mozilla/ipc/Transport.h" // for Transport #include "mozilla/layers/AnimationHelper.h" // for CompositorAnimationStorage @@ -270,6 +271,10 @@ } webgpu::PWebGPUParent* ContentCompositorBridgeParent::AllocPWebGPUParent() { + if (!StaticPrefs::dom_webgpu_enabled()) { + return nullptr; + } + webgpu::WebGPUParent* parent = new webgpu::WebGPUParent(); parent->AddRef(); // IPDL reference return parent; diff -Nru thunderbird-91.7.0+build2/gfx/qcms/build.rs thunderbird-91.8.1+build1/gfx/qcms/build.rs --- thunderbird-91.7.0+build2/gfx/qcms/build.rs 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/qcms/build.rs 2022-04-15 07:40:56.000000000 +0000 @@ -1,3 +1,5 @@ +use rustc_version::{version, Version}; + fn main() { if cfg!(feature = "neon") { if std::env::var_os("RUSTC_BOOTSTRAP").is_none() { @@ -11,4 +13,7 @@ if target.contains("neon") { println!("cargo:rustc-cfg=libcore_neon"); } + if version().unwrap() >= Version::parse("1.60.0-alpha").unwrap() { + println!("cargo:rustc-cfg=std_arch"); + } } diff -Nru thunderbird-91.7.0+build2/gfx/qcms/Cargo.toml thunderbird-91.8.1+build1/gfx/qcms/Cargo.toml --- thunderbird-91.7.0+build2/gfx/qcms/Cargo.toml 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/qcms/Cargo.toml 2022-04-15 07:40:56.000000000 +0000 @@ -20,3 +20,6 @@ [dependencies] libc = {version = "0.2", optional = true } + +[build-dependencies] +rustc_version = "0.2" diff -Nru thunderbird-91.7.0+build2/gfx/qcms/src/gtest.rs thunderbird-91.8.1+build1/gfx/qcms/src/gtest.rs --- thunderbird-91.7.0+build2/gfx/qcms/src/gtest.rs 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/qcms/src/gtest.rs 2022-04-15 07:40:56.000000000 +0000 @@ -5,6 +5,10 @@ transform_util::lut_inverse_interp16, Intent::Perceptual, }; use libc::c_void; + #[cfg(all(target_arch = "arm", std_arch))] + use std::arch::is_arm_feature_detected; + #[cfg(all(target_arch = "aarch64", std_arch))] + use std::arch::is_aarch64_feature_detected; use std::ptr::null_mut; #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] diff -Nru thunderbird-91.7.0+build2/gfx/qcms/src/transform.rs thunderbird-91.8.1+build1/gfx/qcms/src/transform.rs --- thunderbird-91.7.0+build2/gfx/qcms/src/transform.rs 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/qcms/src/transform.rs 2022-04-15 07:40:56.000000000 +0000 @@ -55,6 +55,10 @@ use std::sync::atomic::Ordering; use std::sync::Arc; +#[cfg(all(target_arch = "arm", feature = "neon", std_arch))] +use std::arch::is_arm_feature_detected; +#[cfg(all(target_arch = "aarch64", feature = "neon", std_arch))] +use std::arch::is_aarch64_feature_detected; pub const PRECACHE_OUTPUT_SIZE: usize = 8192; pub const PRECACHE_OUTPUT_MAX: usize = PRECACHE_OUTPUT_SIZE - 1; diff -Nru thunderbird-91.7.0+build2/gfx/src/nsDeviceContext.cpp thunderbird-91.8.1+build1/gfx/src/nsDeviceContext.cpp --- thunderbird-91.7.0+build2/gfx/src/nsDeviceContext.cpp 2022-03-07 21:32:58.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/src/nsDeviceContext.cpp 2022-04-15 07:40:57.000000000 +0000 @@ -705,19 +705,3 @@ return DesktopToLayoutDeviceScale(1.0); } - -bool nsDeviceContext::IsSyncPagePrinting() const { - MOZ_ASSERT(mPrintTarget); - return mPrintTarget->IsSyncPagePrinting(); -} - -void nsDeviceContext::RegisterPageDoneCallback( - PrintTarget::PageDoneCallback&& aCallback) { - MOZ_ASSERT(mPrintTarget && aCallback && !IsSyncPagePrinting()); - mPrintTarget->RegisterPageDoneCallback(std::move(aCallback)); -} -void nsDeviceContext::UnregisterPageDoneCallback() { - if (mPrintTarget) { - mPrintTarget->UnregisterPageDoneCallback(); - } -} diff -Nru thunderbird-91.7.0+build2/gfx/src/nsDeviceContext.h thunderbird-91.8.1+build1/gfx/src/nsDeviceContext.h --- thunderbird-91.7.0+build2/gfx/src/nsDeviceContext.h 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/src/nsDeviceContext.h 2022-04-15 07:40:56.000000000 +0000 @@ -263,10 +263,6 @@ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale(); - bool IsSyncPagePrinting() const; - void RegisterPageDoneCallback(PrintTarget::PageDoneCallback&& aCallback); - void UnregisterPageDoneCallback(); - private: // Private destructor, to discourage deletion outside of Release(): ~nsDeviceContext(); diff -Nru thunderbird-91.7.0+build2/gfx/thebes/PrintTarget.cpp thunderbird-91.8.1+build1/gfx/thebes/PrintTarget.cpp --- thunderbird-91.7.0+build2/gfx/thebes/PrintTarget.cpp 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/thebes/PrintTarget.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -188,11 +188,4 @@ cairo_surface_finish(mCairoSurface); } -void PrintTarget::RegisterPageDoneCallback(PageDoneCallback&& aCallback) { - MOZ_ASSERT(aCallback && !IsSyncPagePrinting()); - mPageDoneCallback = std::move(aCallback); -} - -void PrintTarget::UnregisterPageDoneCallback() { mPageDoneCallback = nullptr; } - } // namespace mozilla::gfx diff -Nru thunderbird-91.7.0+build2/gfx/thebes/PrintTarget.h thunderbird-91.8.1+build1/gfx/thebes/PrintTarget.h --- thunderbird-91.7.0+build2/gfx/thebes/PrintTarget.h 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/thebes/PrintTarget.h 2022-04-15 07:40:56.000000000 +0000 @@ -28,8 +28,6 @@ */ class PrintTarget { public: - typedef std::function PageDoneCallback; - NS_INLINE_DECL_REFCOUNTING(PrintTarget); /// Must be matched 1:1 by an EndPrinting/AbortPrinting call. @@ -130,17 +128,6 @@ */ virtual already_AddRefed GetReferenceDrawTarget(); - /** - * If IsSyncPagePrinting returns true, then a user can assume the content of - * a page was already printed after EndPage(). - * If IsSyncPagePrinting returns false, then a user should register a - * callback function using RegisterPageDoneCallback to receive page print - * done notifications. - */ - virtual bool IsSyncPagePrinting() const { return true; } - void RegisterPageDoneCallback(PageDoneCallback&& aCallback); - void UnregisterPageDoneCallback(); - static void AdjustPrintJobNameForIPP(const nsAString& aJobName, nsCString& aAdjustedJobName); static void AdjustPrintJobNameForIPP(const nsAString& aJobName, @@ -164,8 +151,6 @@ #ifdef DEBUG bool mHasActivePage; #endif - - PageDoneCallback mPageDoneCallback; }; } // namespace gfx diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRGPUChild.cpp thunderbird-91.8.1+build1/gfx/vr/ipc/VRGPUChild.cpp --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRGPUChild.cpp 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRGPUChild.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -9,6 +9,7 @@ #include "mozilla/ipc/Endpoint.h" #include "mozilla/layers/CompositorThread.h" +#include "mozilla/StaticPrefs_dom.h" #include "VRManager.h" namespace mozilla { @@ -21,6 +22,10 @@ MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!sVRGPUChildSingleton); + if (!StaticPrefs::dom_vr_enabled() && !StaticPrefs::dom_vr_webxr_enabled()) { + return false; + } + RefPtr child(new VRGPUChild()); if (!aEndpoint.Bind(child)) { return false; diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRGPUParent.cpp thunderbird-91.8.1+build1/gfx/vr/ipc/VRGPUParent.cpp --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRGPUParent.cpp 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRGPUParent.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -9,6 +9,7 @@ #include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/ProcessChild.h" +#include "mozilla/StaticPrefs_dom.h" namespace mozilla { namespace gfx { @@ -43,6 +44,10 @@ /* static */ RefPtr VRGPUParent::CreateForGPU( Endpoint&& aEndpoint) { + if (!StaticPrefs::dom_vr_enabled() && !StaticPrefs::dom_vr_webxr_enabled()) { + return nullptr; + } + RefPtr vcp = new VRGPUParent(aEndpoint.OtherPid()); GetCurrentSerialEventTarget()->Dispatch( NewRunnableMethod&&>("gfx::VRGPUParent::Bind", vcp, diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRLayerChild.cpp thunderbird-91.8.1+build1/gfx/vr/ipc/VRLayerChild.cpp --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRLayerChild.cpp 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRLayerChild.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -10,6 +10,7 @@ #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/layers/LayersMessages.h" // for TimedTexture #include "mozilla/layers/SyncObject.h" // for SyncObjectClient +#include "mozilla/StaticPrefs_dom.h" #include "mozilla/StaticPrefs_webgl.h" #include "ClientWebGLContext.h" @@ -122,6 +123,10 @@ // static PVRLayerChild* VRLayerChild::CreateIPDLActor() { + if (!StaticPrefs::dom_vr_enabled() && !StaticPrefs::dom_vr_webxr_enabled()) { + return nullptr; + } + VRLayerChild* c = new VRLayerChild(); c->AddIPDLReference(); return c; diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRLayerParent.cpp thunderbird-91.8.1+build1/gfx/vr/ipc/VRLayerParent.cpp --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRLayerParent.cpp 2022-03-07 21:32:58.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRLayerParent.cpp 2022-04-15 07:40:57.000000000 +0000 @@ -14,9 +14,12 @@ namespace gfx { VRLayerParent::VRLayerParent(uint32_t aVRDisplayID, const uint32_t aGroup) - : mIPCOpen(true), mVRDisplayID(aVRDisplayID), mGroup(aGroup) {} + : mIPCOpen(true), mDestroyed(false), mGroup(aGroup) {} -VRLayerParent::~VRLayerParent() { MOZ_COUNT_DTOR(VRLayerParent); } +VRLayerParent::~VRLayerParent() { + Destroy(); + MOZ_COUNT_DTOR(VRLayerParent); +} mozilla::ipc::IPCResult VRLayerParent::RecvDestroy() { Destroy(); @@ -26,12 +29,10 @@ void VRLayerParent::ActorDestroy(ActorDestroyReason aWhy) { mIPCOpen = false; } void VRLayerParent::Destroy() { - if (mVRDisplayID) { + if (!mDestroyed) { VRManager* vm = VRManager::Get(); vm->RemoveLayer(this); - // 0 will never be a valid VRDisplayID; we can use it to indicate that - // we are destroyed and no longer associated with a display. - mVRDisplayID = 0; + mDestroyed = true; } if (mIPCOpen) { @@ -42,7 +43,7 @@ mozilla::ipc::IPCResult VRLayerParent::RecvSubmitFrame( const layers::SurfaceDescriptor& aTexture, const uint64_t& aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) { - if (mVRDisplayID) { + if (!mDestroyed) { VRManager* vm = VRManager::Get(); vm->SubmitFrame(this, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect); } diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRLayerParent.h thunderbird-91.8.1+build1/gfx/vr/ipc/VRLayerParent.h --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRLayerParent.h 2022-03-07 21:32:58.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRLayerParent.h 2022-04-15 07:40:56.000000000 +0000 @@ -23,7 +23,6 @@ const layers::SurfaceDescriptor& aTexture, const uint64_t& aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) override; virtual mozilla::ipc::IPCResult RecvDestroy() override; - uint32_t GetDisplayID() const { return mVRDisplayID; } uint32_t GetGroup() const { return mGroup; } protected: @@ -34,7 +33,7 @@ bool mIPCOpen; - uint32_t mVRDisplayID; + bool mDestroyed; gfx::Rect mLeftEyeRect; gfx::Rect mRightEyeRect; uint32_t mGroup; diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRManagerParent.cpp thunderbird-91.8.1+build1/gfx/vr/ipc/VRManagerParent.cpp --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRManagerParent.cpp 2022-03-07 21:32:57.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRManagerParent.cpp 2022-04-15 07:40:57.000000000 +0000 @@ -10,6 +10,7 @@ #include "mozilla/gfx/PVRManagerParent.h" #include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/ProtocolTypes.h" +#include "mozilla/StaticPrefs_dom.h" #include "mozilla/ipc/ProtocolUtils.h" // for IToplevelProtocol #include "mozilla/TimeStamp.h" // for TimeStamp #include "mozilla/Unused.h" @@ -45,6 +46,10 @@ PVRLayerParent* VRManagerParent::AllocPVRLayerParent(const uint32_t& aDisplayID, const uint32_t& aGroup) { + if (!StaticPrefs::dom_vr_enabled() && !StaticPrefs::dom_vr_webxr_enabled()) { + return nullptr; + } + RefPtr layer; layer = new VRLayerParent(aDisplayID, aGroup); VRManager* vm = VRManager::Get(); diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRProcessChild.cpp thunderbird-91.8.1+build1/gfx/vr/ipc/VRProcessChild.cpp --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRProcessChild.cpp 2022-03-07 21:32:58.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRProcessChild.cpp 2022-04-15 07:40:57.000000000 +0000 @@ -9,6 +9,7 @@ #include "mozilla/BackgroundHangMonitor.h" #include "mozilla/ipc/IOThreadChild.h" #include "mozilla/ipc/ProcessUtils.h" +#include "mozilla/StaticPrefs_dom.h" using namespace mozilla; using namespace mozilla::gfx; diff -Nru thunderbird-91.7.0+build2/gfx/vr/ipc/VRProcessParent.cpp thunderbird-91.8.1+build1/gfx/vr/ipc/VRProcessParent.cpp --- thunderbird-91.7.0+build2/gfx/vr/ipc/VRProcessParent.cpp 2022-03-07 21:32:58.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/ipc/VRProcessParent.cpp 2022-04-15 07:40:56.000000000 +0000 @@ -42,12 +42,6 @@ } VRProcessParent::~VRProcessParent() { - // Cancel all tasks. We don't want anything triggering after our caller - // expects this to go away. - { - MonitorAutoLock lock(mMonitor); - mTaskFactory.RevokeAll(); - } MOZ_COUNT_DTOR(VRProcessParent); } @@ -134,6 +128,13 @@ void VRProcessParent::DestroyProcess() { if (mLaunchThread) { + // Cancel all tasks. We don't want anything triggering after our caller + // expects this to go away. + { + MonitorAutoLock lock(mMonitor); + mTaskFactory.RevokeAll(); + } + mLaunchThread->Dispatch(NS_NewRunnableFunction("DestroyProcessRunnable", [this] { Destroy(); })); } @@ -155,6 +156,12 @@ return false; } + if (!StaticPrefs::dom_vr_enabled() && + !StaticPrefs::dom_vr_webxr_enabled()) { + NS_WARNING("VR is not enabled when trying to create a VRChild"); + return false; + } + mVRChild = MakeUnique(this); DebugOnly rv = mVRChild->Open( diff -Nru thunderbird-91.7.0+build2/gfx/vr/VRManager.cpp thunderbird-91.8.1+build1/gfx/vr/VRManager.cpp --- thunderbird-91.7.0+build2/gfx/vr/VRManager.cpp 2022-03-07 21:32:58.000000000 +0000 +++ thunderbird-91.8.1+build1/gfx/vr/VRManager.cpp 2022-04-15 07:40:57.000000000 +0000 @@ -858,6 +858,9 @@ } void VRManager::StopAllHaptics() { + if (mState != VRManagerState::Active) { + return; + } for (size_t i = 0; i < mozilla::ArrayLength(mBrowserState.hapticState); i++) { ClearHapticSlot(i); } @@ -1015,6 +1018,10 @@ } void VRManager::ResetPuppet(VRManagerParent* aManagerParent) { + if (!StaticPrefs::dom_vr_puppet_enabled()) { + return; + } + mManagerParentsWaitingForPuppetReset.Insert(aManagerParent); if (mManagerParentRunningPuppet != nullptr) { Unused << mManagerParentRunningPuppet @@ -1516,6 +1523,10 @@ NS_IMETHODIMP VRManager::Observe(nsISupports* subject, const char* topic, const char16_t* data) { + if (!StaticPrefs::dom_vr_enabled() && !StaticPrefs::dom_vr_webxr_enabled()) { + return NS_OK; + } + if (!strcmp(topic, "application-background")) { // StopTasks() is called later in the timer thread based on this flag to // avoid threading issues. diff -Nru thunderbird-91.7.0+build2/image/decoders/nsGIFDecoder2.cpp thunderbird-91.8.1+build1/image/decoders/nsGIFDecoder2.cpp --- thunderbird-91.7.0+build2/image/decoders/nsGIFDecoder2.cpp 2022-03-07 21:32:58.000000000 +0000 +++ thunderbird-91.8.1+build1/image/decoders/nsGIFDecoder2.cpp 2022-04-15 07:40:57.000000000 +0000 @@ -91,8 +91,10 @@ mGIFOpen(false), mSawTransparency(false), mSwizzleFn(nullptr) { - // Clear out the structure, excluding the arrays. + // Clear out the structure, excluding the arrays. Ensure that the global + // colormap is initialized as opaque. memset(&mGIFStruct, 0, sizeof(mGIFStruct)); + memset(mGIFStruct.global_colormap, 0xFF, sizeof(mGIFStruct.global_colormap)); // Each color table will need to be unpacked. mSwizzleFn = SwizzleRow(SurfaceFormat::R8G8B8, SurfaceFormat::OS_RGBA); @@ -854,6 +856,8 @@ mGIFStruct.local_colormap_buffer_size = mColormapSize; mGIFStruct.local_colormap = static_cast(moz_xmalloc(mColormapSize)); + // Ensure the local colormap is initialized as opaque. + memset(mGIFStruct.local_colormap, 0xFF, mColormapSize); } else { mColormapSize = mGIFStruct.local_colormap_buffer_size; } diff -Nru thunderbird-91.7.0+build2/ipc/glue/Shmem.cpp thunderbird-91.8.1+build1/ipc/glue/Shmem.cpp --- thunderbird-91.7.0+build2/ipc/glue/Shmem.cpp 2022-03-07 21:32:59.000000000 +0000 +++ thunderbird-91.8.1+build1/ipc/glue/Shmem.cpp 2022-04-15 07:40:57.000000000 +0000 @@ -241,6 +241,9 @@ mSize = static_cast(header->mSize); size_t pageSize = SharedMemory::SystemPageSize(); + MOZ_ASSERT(mSegment->Size() - (2 * pageSize) >= mSize, + "illegal size in shared memory segment"); + // transition into the "mapped" state by protecting the front and // back sentinels (which guard against buffer under/overflows) mSegment->Protect(frontSentinel, pageSize, RightsNone); @@ -373,6 +376,13 @@ #else // !defined(DEBUG) +Shmem::Shmem(PrivateIPDLCaller, SharedMemory* aSegment, id_t aId) + : mSegment(aSegment), mData(aSegment->memory()), mSize(0), mId(aId) { + mSize = static_cast(*PtrToSize(mSegment)); + MOZ_RELEASE_ASSERT(mSegment->Size() - sizeof(uint32_t) >= mSize, + "illegal size in shared memory segment"); +} + // static already_AddRefed Shmem::Alloc(PrivateIPDLCaller, size_t aNBytes, diff -Nru thunderbird-91.7.0+build2/ipc/glue/Shmem.h thunderbird-91.8.1+build1/ipc/glue/Shmem.h --- thunderbird-91.7.0+build2/ipc/glue/Shmem.h 2022-03-07 21:32:59.000000000 +0000 +++ thunderbird-91.8.1+build1/ipc/glue/Shmem.h 2022-04-15 07:40:57.000000000 +0000 @@ -84,14 +84,7 @@ Shmem(const Shmem& aOther) = default; -#if !defined(DEBUG) - Shmem(PrivateIPDLCaller, SharedMemory* aSegment, id_t aId) - : mSegment(aSegment), mData(aSegment->memory()), mSize(0), mId(aId) { - mSize = static_cast(*PtrToSize(mSegment)); - } -#else Shmem(PrivateIPDLCaller, SharedMemory* aSegment, id_t aId); -#endif ~Shmem() { // Shmem only holds a "weak ref" to the actual segment, which is diff -Nru thunderbird-91.7.0+build2/js/src/jit/JitFrames.cpp thunderbird-91.8.1+build1/js/src/jit/JitFrames.cpp --- thunderbird-91.7.0+build2/js/src/jit/JitFrames.cpp 2022-03-07 21:32:59.000000000 +0000 +++ thunderbird-91.8.1+build1/js/src/jit/JitFrames.cpp 2022-04-15 07:40:59.000000000 +0000 @@ -1030,13 +1030,15 @@ TraceRoot(trc, layout->stubCode(), "ion-ic-call-code"); } -#ifdef JS_CODEGEN_MIPS32 +#if defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) uint8_t* alignDoubleSpill(uint8_t* pointer) { uintptr_t address = reinterpret_cast(pointer); - address &= ~(ABIStackAlignment - 1); + address &= ~(uintptr_t(ABIStackAlignment) - 1); return reinterpret_cast(address); } +#endif +#ifdef JS_CODEGEN_MIPS32 static void TraceJitExitFrameCopiedArguments(JSTracer* trc, const VMFunctionData* f, ExitFooterFrame* footer) { diff -Nru thunderbird-91.7.0+build2/js/src/jit/JitFrames.h thunderbird-91.8.1+build1/js/src/jit/JitFrames.h --- thunderbird-91.7.0+build2/js/src/jit/JitFrames.h 2022-03-07 21:33:00.000000000 +0000 +++ thunderbird-91.8.1+build1/js/src/jit/JitFrames.h 2022-04-15 07:40:59.000000000 +0000 @@ -196,11 +196,11 @@ // Returns the JSScript associated with the topmost JIT frame. JSScript* GetTopJitJSScript(JSContext* cx); -#ifdef JS_CODEGEN_MIPS32 +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_ARM64) uint8_t* alignDoubleSpill(uint8_t* pointer); #else inline uint8_t* alignDoubleSpill(uint8_t* pointer) { - // This is NO-OP on non-MIPS platforms. + // This is a no-op on most platforms. return pointer; } #endif diff -Nru thunderbird-91.7.0+build2/js/src/jit/MIR.h thunderbird-91.8.1+build1/js/src/jit/MIR.h --- thunderbird-91.7.0+build2/js/src/jit/MIR.h 2022-03-07 21:33:01.000000000 +0000 +++ thunderbird-91.8.1+build1/js/src/jit/MIR.h 2022-04-15 07:40:58.000000000 +0000 @@ -6896,7 +6896,8 @@ return congruentIfOperandsEqual(other); } AliasSet getAliasSet() const override { - return AliasSet::Load(AliasSet::UnboxedElement); + return AliasSet::Load(AliasSet::UnboxedElement | AliasSet::ObjectFields | + AliasSet::ArrayBufferViewLengthOrOffset); } bool canProduceFloat32() const override { return arrayType_ == Scalar::Float32; diff -Nru thunderbird-91.7.0+build2/js/src/wasm/WasmFrame.cpp thunderbird-91.8.1+build1/js/src/wasm/WasmFrame.cpp --- thunderbird-91.7.0+build2/js/src/wasm/WasmFrame.cpp 2022-03-07 21:33:06.000000000 +0000 +++ thunderbird-91.8.1+build1/js/src/wasm/WasmFrame.cpp 2022-04-15 07:41:03.000000000 +0000 @@ -54,8 +54,10 @@ static_assert(WasmStackAlignment >= Alignment, "Aligned by ABI before pushing DebugFrame"); +#ifndef JS_CODEGEN_NONE static_assert((offsetof(DebugFrame, frame_) + sizeof(Frame)) % Alignment == 0, "Aligned after pushing DebugFrame"); +#endif #ifdef JS_CODEGEN_ARM64 // This constraint may or may not be necessary. If you hit this because // you've changed the frame size then feel free to remove it, but be extra diff -Nru thunderbird-91.7.0+build2/l10n/ar/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/ar/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/ar/devtools/client/aboutdebugging.ftl 2022-03-07 21:35:48.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ar/devtools/client/aboutdebugging.ftl 2022-04-15 07:50:26.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = التنقيح - الإعداد - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = التنقيح - زمن التشغيل / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = { -brand-shorter-name } هذا - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = الإعداد - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = الربط عبر USB يعمل - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = الربط عبر USB لا يعمل - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = متصّل # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = غير متصّل - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = لم تُكتشف أي أجهزة - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = اتّصل - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = يتّصل… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = فشل الاتصال - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = ما زال الاتصال جارٍ، طالِح الرسائل في المتصفح الهدف - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = انتهت المهلة للاتصال - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = ينتظر المتصفح… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = مفصول - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page # (currently: https://developer.mozilla.org/docs/Tools/about:debugging) about-debugging-sidebar-support = دعم التنقيح - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = أيقونة المساعدة - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = أنعِش الأجهزة @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = الإعداد - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = اضبط الطريقة التي تريد بها الاتصال بجهازك لتنقيحه. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = استعمل { about-debugging-this-firefox-runtime-name } لتنقّح الامتدادات وعمّال الخدمة في إصدارة { -brand-shorter-name } هذه. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = أوصِل جهازا - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = بتفعيل هذا تُنزّل وتُضيف المكوّنات المطلوبة إلى { -brand-shorter-name } لتنقيح أجهزة أندرويد عبر USB. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = فعّل الأجهزة عبر USB - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = عطّل الأجهزة عبر USB - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = يحدّث… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = مفعّل about-debugging-setup-usb-status-disabled = معطّل about-debugging-setup-usb-status-updating = يحدّث… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = فعّل قائمة ”مطوّر البرامج/Developer“ في جهاز أندرويد لديك. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = فعّل ”تصحيح أخطاء USB/‏USB Debugging“ في قائمة ”مطور البرامج/Developer“. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = فعّل التنقيح عبر USB في متصفح Firefox على أجهزة أندرويد. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = أوصِل جهاز أندرويد بهذا الحاسوب. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. # The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB about-debugging-setup-usb-troubleshoot = أتواجه مشاكل بالاتصال بجهازك عبر USB؟ تعقّب المشكلة - # Network section of the Setup page about-debugging-setup-network = .title = مكان على الشبكة - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. # The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network about-debugging-setup-network-troubleshoot = أتواجه مشاكل بالاتصال بمكان على الشبكة؟ تعقّب المشكلة - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = أضِف - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = لم تُضف أي أماكن على الشبكة بعد. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = المضيف - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = أزِل - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = المضيف ”{ $host-value }“ غير صالح. التنسيق الذي توقّعتُه هو ‎“hostname:portnumber”‎. - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,22 +162,18 @@ # Title of the processes category. about-debugging-runtime-processes = .name = العمليات - # This string is displayed in the runtime page if the current configuration of the # target runtime is incompatible with service workers. "Learn more" points to MDN. # https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible about-debugging-runtime-service-workers-not-compatible = إعدادات المتصفح لديك غير متوافقة مع عمّال الخدمة. اطّلع على المزيد - # This string is displayed in the runtime page if the remote browser version is too old. # "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = إصدارة المتصفّح المتّصل قديمة ({ $runtimeVersion }). أدنى إصدارة مدعومة هي ({ $minVersion }). عملية الإعداد هذه غير مدعومة وقد لا تعمل أدوات المطوّرين بناء على ذلك. من فضلك حدّث المتصفّح المتّصل. مواجهة الأعطال - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = لا يمكن لإصدارة متصفّح Firefox هذه تنقيح Firefox لأندرويد (68). ننصح بتنزيل النسخة الليلية من Firefox لأندرويد على هاتفك لإجراء الاختبارات. تفاصيل أكثر - # This string is displayed in the runtime page if the remote browser version is too recent. # "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) @@ -225,16 +181,15 @@ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = إصدارة المتصفّح المتّصل ({ $runtimeVersion }، معرّف البناء { $runtimeID }) أحدث من إصدارة { -brand-shorter-name } هذه ({ $localVersion }، معرّف البناء { $localID }). عملية الإعداد هذه غير مدعومة وقد لا تعمل أدوات المطوّرين بناء على ذلك. من فضلك حدّث Firefox. مواجهة الأعطال - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = ‏{ $name } ‏({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = اقطع الاتصال - +# Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. +about-debugging-profiler-dialog-title2 = محلّل الأداء # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -245,81 +200,61 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = لا شيء بعد. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = افحص - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = حمّل إضافة مؤقتا… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = حدث عُطل أثناء تثبيت الإضافة مؤقتا. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = أعِد التحميل - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = أزِل - # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = اختر ملف manifest.json أو أرشيف ‎.xpi/.zip - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = لامتداد WebExtension هذا معرّف مؤقّت. اطّلع على المزيد - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = المكان - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = معرّف الامتداد - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = ابدأ .disabledTitle = بدء عامل الخدمة معطّل حاليًا إذ { -brand-shorter-name } يعمل بأكثر من سيرورة - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = يعمل - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = متوقّف - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = يُسجّل - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = لم يُحمّل اللسان تمامًا ولا يمكن فحصه - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = السيرورة الأساسية - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = شريط أدوات السيرورات المتعددة - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = أغلِق الرسالة - # Label text used for the error details of message component. about-debugging-message-details-label-error = تفاصيل العُطل - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = تفاصيل التحذير - # Label text used for default state of details of message component. about-debugging-message-details-label = التفاصيل diff -Nru thunderbird-91.7.0+build2/l10n/ar/devtools/client/components.properties thunderbird-91.8.1+build1/l10n/ar/devtools/client/components.properties --- thunderbird-91.7.0+build2/l10n/ar/devtools/client/components.properties 2022-03-07 21:35:48.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ar/devtools/client/components.properties 2022-04-15 07:50:26.000000000 +0000 @@ -22,3 +22,14 @@ # LOCALIZATION NOTE (notificationBox.closeTooltip): The content of a tooltip that # appears when hovering over the close button in a notification box. notificationBox.closeTooltip=أغلق هذه الرسالة + +# LOCALIZATION NOTE (appErrorBoundary.description): This is the information displayed +# once the panel errors. +# %S represents the name of panel which has the crash. +appErrorBoundary.description=انهارت اللوحة %S. + +# LOCALIZATION NOTE (appErrorBoundary.fileBugButton): This is the text that appears in +# the button to visit the bug filing link. + +# LOCALIZATION NOTE (appErrorBoundary.reloadPanelInfo): This is the text that appears +# after the panel errors to instruct the user to reload the panel. diff -Nru thunderbird-91.7.0+build2/l10n/ar/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/ar/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/ar/devtools/client/netmonitor.properties 2022-03-07 21:35:48.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ar/devtools/client/netmonitor.properties 2022-04-15 07:50:26.000000000 +0000 @@ -89,6 +89,9 @@ # available for shown. responseEmptyText=ما من بيانات استجابة لهذا الطلب +# LOCALIZATION NOTE (paramsNoPayloadText): This is the text displayed in the +# request tab of the network details pane when there are no params available. + # LOCALIZATION NOTE (paramsFilterText): This is the text displayed in the # request tab of the network details pane for the filtering input. paramsFilterText=رشّح معاملات الطلب @@ -817,6 +820,9 @@ # in the action bar's search tab netmonitor.actionbar.search=ابحث +# LOCALIZATION NOTE (netmonitor.actionbar.HTTPCustomRequest): This is the label displayed +# in the action bar's edit and resend tab + # LOCALIZATION NOTE (messagesTruncated): This is the text displayed # in the messages panel when the number of messages is over the # truncation limit. @@ -963,6 +969,9 @@ # in the network toolbar for the search button. netmonitor.toolbar.search=ابحث +# LOCALIZATION NOTE (netmonitor.toolbar.HTTPCustomRequest): This is the tooltip label displayed +# in the network toolbar for the new HTTP Custom Request button. + # LOCALIZATION NOTE (netmonitor.toolbar.resetColumns): This is the label # displayed in the network table header context menu. netmonitor.toolbar.resetColumns=صفّر الأعمدة @@ -1032,8 +1041,15 @@ # on the button in the headers tab that toggle view for raw request/response headers # from the currently displayed request +# LOCALIZATION NOTE (netmonitor.headers.blockedByCORS): This is the message displayed +# in the notification shown when a request has been blocked by CORS with a more +# specific reason shown in the parenthesis + +#LOCALIZATION NOTE (netmonitor.headers.blockedByCORSTooltip): This is the tooltip +# displayed on the learnmore link of the blocked by CORS notification. + # LOCALIZATION NOTE (netmonitor.response.name): This is the label displayed -# in the network details response tab identifying an image's file name. +# in the network details response tab identifying an image's file name or font face's name. netmonitor.response.name=الاسم: # LOCALIZATION NOTE (netmonitor.response.dimensions): This is the label displayed @@ -1041,9 +1057,13 @@ netmonitor.response.dimensions=الأبعاد: # LOCALIZATION NOTE (netmonitor.response.mime): This is the label displayed -# in the network details response tab identifying an image's mime. +# in the network details response tab identifying an image's or font's MIME type. netmonitor.response.mime=نوع MIME: +# LOCALIZATION NOTE (netmonitor.response.fontPreviewFailed): This is the notice displayed +# in the network details response tab if the font preview could not be generated due to +# an error. + # LOCALIZATION NOTE (netmonitor.timings.blocked): This is the label displayed # in the network details timings tab identifying the amount of time spent # in a "blocked" state. @@ -1151,10 +1171,12 @@ # LOCALIZATION NOTE (netmonitor.trackingResource.enhancedTrackingProtection): This is # the label used in the Network monitor panel for showing enhanced tracking protection. +netmonitor.trackingResource.enhancedTrackingProtection=الحماية الموسّعة من التعقب # LOCALIZATION NOTE (netmonitor.enhancedTrackingProtection.learnMore): This is the label # displayed in the network details headers tab, with a link to external documentation for # enhanced tracking protection. +netmonitor.enhancedTrackingProtection.learnMore=اطّلع على المزيد عن الحماية الموسّعة من التعقب # LOCALIZATION NOTE (netmonitor.context.copy): This is the label displayed # for the copy sub-menu in the context menu for a request @@ -1202,6 +1224,8 @@ # a target platform to the label for "Copy as cURL" command # e.g. Copy as cURL (Windows) # Localized label for "Copy as cURL": %S +netmonitor.context.copyAsCurl.win=%S (وِندوز) +netmonitor.context.copyAsCurl.posix=%S (POSIX) # LOCALIZATION NOTE (netmonitor.context.copyAsFetch): This is the label displayed # on the context menu that copies the selected request as a fetch request. @@ -1472,4 +1496,3 @@ # LOCALIZATION NOTE (netmonitor.errorpanel.fileBugButton): This is the text that appears in the button to visit the bug filing link. # LOCALIZATION NOTE (netmonitor.errorpanel.reloadPanelInfo): This is the text that appears after Network panel errors to instruct the user to reload the panel. - diff -Nru thunderbird-91.7.0+build2/l10n/ar/toolkit/chrome/global/global-extension-fields.properties thunderbird-91.8.1+build1/l10n/ar/toolkit/chrome/global/global-extension-fields.properties --- thunderbird-91.7.0+build2/l10n/ar/toolkit/chrome/global/global-extension-fields.properties 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ar/toolkit/chrome/global/global-extension-fields.properties 2022-04-15 07:50:26.000000000 +0000 @@ -0,0 +1,6 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# LOCALIZATION NOTE (extension.default-theme@mozilla.org.name, extension.default-theme@mozilla.org.description): This is displayed in about:addons -> Appearance +extension.default-theme@mozilla.org.description=اتبع إعدادات نظام التشغيل لعرض الأزرار والقوائم والنوافذ. diff -Nru thunderbird-91.7.0+build2/l10n/be/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/be/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/be/devtools/client/debugger.properties 2022-03-07 21:36:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/be/devtools/client/debugger.properties 2022-04-15 07:50:39.000000000 +0000 @@ -642,6 +642,16 @@ ignoreContextItem.unignore=Не ігнараваць крыніцу ignoreContextItem.unignore.accesskey=Н +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Ігнараваць радок +ignoreContextItem.ignoreLine.accesskey=н + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Не ігнараваць радок +ignoreContextItem.unignoreLine.accesskey=р + # LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated # with the ignore lines context menu item ignoreContextItem.ignoreLines=Ігнараваць радкі diff -Nru thunderbird-91.7.0+build2/l10n/be/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/be/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/be/devtools/client/netmonitor.properties 2022-03-07 21:36:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/be/devtools/client/netmonitor.properties 2022-04-15 07:50:40.000000000 +0000 @@ -1460,10 +1460,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Радок запыта: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=Параметры URL + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Загалоўкі запыта: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Загалоўкі + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=назва + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=значэнне + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Цела + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=карыснае змесціва + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Цела запыта: @@ -1476,6 +1500,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Скасаваць +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Ачысціць + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Выдаліць элемент + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Назад diff -Nru thunderbird-91.7.0+build2/l10n/be/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/be/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/be/netwerk/necko.properties 2022-03-07 21:36:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/be/netwerk/necko.properties 2022-04-15 07:50:39.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Кукі “%1$S” быў адхілены, бо скончыўся тэрмін яго дзеяння. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Кукі “%1$S” быў адхілены, бо ён знаходзіцца ў міжсайтавым кантэксце, а ягоны атрыбут “SameSite” мае значэнне “Lax” альбо “Strict”. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Папярэджанне: ‘%1$S’ састарэлы, калі ласка, выкарыстоўвайце ‘%2$S’ diff -Nru thunderbird-91.7.0+build2/l10n/be/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/be/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/be/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:35:59.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/be/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:50:39.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Без засечак # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Закрыць Рэжым чытання @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Колеравая схема Светлая aboutReader.toolbar.colorschemedark = Колеравая схема Цёмная aboutReader.toolbar.colorschemesepia = Колеравая схема Сэпія +aboutReader.toolbar.colorschemeauto = Аўтаматычная каляровая схема diff -Nru thunderbird-91.7.0+build2/l10n/be/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/be/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/be/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:36:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/be/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:50:39.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Сокет # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = IPC Actor у пясочніцы ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/bg/toolkit/toolkit/about/aboutSupport.ftl thunderbird-91.8.1+build1/l10n/bg/toolkit/toolkit/about/aboutSupport.ftl --- thunderbird-91.7.0+build2/l10n/bg/toolkit/toolkit/about/aboutSupport.ftl 2022-03-07 21:36:06.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/bg/toolkit/toolkit/about/aboutSupport.ftl 2022-04-15 07:50:47.000000000 +0000 @@ -4,7 +4,6 @@ page-title = Отстраняване на неизправности page-subtitle = Тази страница съдържа техническа информация, която може да ви е от полза, когато се опитвате да решите проблем. Ако търсите отговори на често задавани въпроси за { -brand-short-name }, проверете в нашата страница за поддръжка. - crashes-title = Доклади за сривове crashes-id = Идентификатор на доклад crashes-send-date = Изпратен @@ -103,6 +102,7 @@ sandbox-sys-call-proc-type = Вид процес sandbox-sys-call-number = Syscall sandbox-sys-call-args = Аргументи +clear-startup-cache-title = Опитайте да изчистите междинната памет за стартиране ## Media titles @@ -156,7 +156,6 @@ [one] Доклади за сривовете през последния { $days } ден *[other] Доклади за сривовете през последните { $days } дена } - # Variables # $minutes (integer) - Number of minutes since crash crashes-time-minutes = @@ -164,7 +163,6 @@ [one] преди { $minutes } минута *[other] преди { $minutes } минути } - # Variables # $hours (integer) - Number of hours since crash crashes-time-hours = @@ -172,7 +170,6 @@ [one] преди { $hours } час *[other] преди { $hours } часа } - # Variables # $days (integer) - Number of days since crash crashes-time-days = @@ -180,7 +177,6 @@ [one] преди { $days } ден *[other] преди { $days } дена } - # Variables # $reports (integer) - Number of pending reports pending-reports = @@ -188,7 +184,6 @@ [one] Всички доклади за сривове (включително { $reports } изчакващ срив в дадения времеви диапазон) *[other] Всички доклади за сривове (включително { $reports } изчакващи срива в дадения времеви диапазон) } - raw-data-copied = Суровите данни са копирани в системния буфер text-copied = Текстът е копиран в системния буфер @@ -201,11 +196,9 @@ # Variables # $driverVersion - The graphics driver version string try-newer-driver = Вашият графичен драйвер е блокиран. Опитайте да обновите драйвера си до версия { $driverVersion } или по-нова. - # "ClearType" is a proper noun and should not be translated. Feel free to leave English strings if # there are no good translations, these are only used in about:support clear-type-parameters = Параметри на ClearType - compositing = Сглобяване hardware-h264 = Хардуерно декодиране на H264 main-thread-no-omtc = главна нишка, без OMTC @@ -219,7 +212,6 @@ found = Наличен missing = Липсващ - gpu-process-pid = GPUProcessPid gpu-process = GPUProcess gpu-description = Описание @@ -242,14 +234,11 @@ webgl2-version = Версия на драйвера за WebGL 2 webgl2-driver-extensions = Разширения на драйвера за WebGL 2 webgl2-extensions = Разширения на WebGL 2 - # Variables # $failureCode (string) - String that can be searched in the source tree. unknown-failure = В списъка на блокираните: код на грешка { $failureCode } - d3d11layers-crash-guard = Сглобяване с D3D11 glcontext-crash-guard = OpenGL - reset-on-next-restart = Анулиране при следващото рестартиране gpu-process-kill-button = Прекъсване на процес на GPU gpu-device-reset = Нулиране на устройството @@ -259,10 +248,8 @@ off-main-thread-paint-enabled = Изчертаване в отделна нишка включено off-main-thread-paint-worker-count = Брой сервизни нишки, изчертаващи в отделна нишка target-frame-rate = Целева честота на кадрите - min-lib-versions = Очаквана минимална версия loaded-lib-versions = Използвана версия - has-seccomp-bpf = Seccomp-BPF (филтриране на системни извиквания) has-seccomp-tsync = Синхронизиране на нишката на Seccomp has-user-namespaces = Потребителски пространства от имена @@ -274,12 +261,10 @@ sandbox-proc-type-content = съдържание sandbox-proc-type-file = съдържание на файл sandbox-proc-type-media-plugin = приставка за медия - # Variables # $remoteWindows (integer) - Number of remote windows # $totalWindows (integer) - Number of total windows multi-process-windows = { $remoteWindows }/{ $totalWindows } - async-pan-zoom = Асинхронно преместване / мащабиране apz-none = няма wheel-enabled = използване на колелцето на мишката diff -Nru thunderbird-91.7.0+build2/l10n/ca/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/ca/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/ca/devtools/client/aboutdebugging.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/devtools/client/aboutdebugging.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Depuració - Configuració - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Depuració - Entorn d'execució / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Aquest { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Configuració - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB activat - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB desactivat - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Connectat # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Desconnectat - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = No s'ha descobert cap dispositiu - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Connecta - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = S'està connectant… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = La connexió ha fallat - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = La connexió encara està pendent, comproveu si hi ha missatges en el navegador de destí - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = S'ha esgotat el temps d'espera de la connexió - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = S'està esperant el navegador… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Desconnectat - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Assistència per a la depuració - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Icona d'ajuda - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Actualitza els dispositius @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Configuració - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Configureu el mètode de connexió amb què voleu depurar remotament el vostre dispositiu. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Utilitzeu { about-debugging-this-firefox-runtime-name } per depurar extensions i processos de treball de servei en aquesta versió del { -brand-shorter-name }. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Connecteu un dispositiu - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Si activeu aquesta opció, es baixaran i s'afegiran els components necessaris de depuració USB de l'Android en el { -brand-shorter-name }. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = Activa els dispositius USB - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = Desactiva els dispositius USB - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = S'està actualitzant… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Activat about-debugging-setup-usb-status-disabled = Desactivat about-debugging-setup-usb-status-updating = S'està actualitzant… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Activeu el menú «Opcions per a desenvolupadors» en el dispositiu Android. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Activeu la «Depuració USB» en el menú «Opcions per a desenvolupadors» de l'Android. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Activeu la depuració USB en el Firefox en el dispositiu Android. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Connecteu el dispositiu Android a l'ordinador. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Teniu problemes per connectar-vos al dispositiu USB? Resolució de problemes - # Network section of the Setup page about-debugging-setup-network = .title = Ubicació de xarxa - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Teniu problemes per connectar-vos mitjançant la ubicació de xarxa? Resolució de problemes - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Afegeix - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = Encara no s'ha afegit cap ubicació de xarxa. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Amfitrió - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Elimina - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = L'amfitrió «{ $host-value }» no és vàlid. El format esperat és «nom_amfitrió:número_port». - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,36 +162,28 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Processos - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Analitza el rendiment - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = La configuració del navegador no és compatible amb els processos de treball de servei. Més informació - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Desconnecta - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Activa la sol·licitud de connexió - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Desactiva la sol·licitud de connexió - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Analitzador de rendiment - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -242,104 +194,81 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = De moment, cap. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Inspecciona - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Carrega un complement temporal… - +# Text displayed when trying to install a temporary extension in the "This Firefox" page. +about-debugging-tmp-extension-install-error = S'ha produït un error durant la instal·lació del complement temporal. # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Torna a carregar - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Elimina - # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Seleccioneu un fitxer manifest.json o un arxiu .xpi/.zip - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Aquesta WebExtension té un ID temporal. Més informació - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = URL de manifest - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = UUID intern - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Ubicació - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = ID d'extensió - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Inicia .disabledTitle = L'inici d'un procés de treball de servei està desactivat pel multiprocés del { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Suprimeix el registre - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = S'està executant - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Aturat - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = S'està registrant - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Àmbit - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Servei de transferència Push - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = La inspecció dels processos de treball de servei està desactivada pel multiprocés del { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Aquesta pestanya no s'ha acabat de carregat i no es pot inspeccionar - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Procés principal - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Caixa d'eines de multiprocés - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Tanca el missatge - # Label text used for the error details of message component. about-debugging-message-details-label-error = Detalls de l'error - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Detalls de l'avís - # Label text used for default state of details of message component. about-debugging-message-details-label = Detalls diff -Nru thunderbird-91.7.0+build2/l10n/ca/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/ca/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/ca/devtools/client/debugger.properties 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/devtools/client/debugger.properties 2022-04-15 07:51:00.000000000 +0000 @@ -47,30 +47,6 @@ # context menu to remove a directory as root directory removeDirectoryRoot.label=Elimina el directori arrel -# LOCALIZATION NOTE (blackBoxAllInGroup.label): This is the text that appears in the -# context submenu to blackbox all files inside of the selected group - -# LOCALIZATION NOTE (unblackBoxAllInGroup.label): This is the text that appears in the -# context submenu to unblackbox all files inside of the selected group - -# LOCALIZATION NOTE (blackBoxAllOutsideGroup.label): This is the text that appears in the -# context submenu to blackbox all files outside of the selected group - -# LOCALIZATION NOTE (unblackBoxAllOutsideGroup.label): This is the text that appears in the -# context submenu to unblackbox all files outside of the selected group - -# LOCALIZATION NOTE (blackBoxAllInDir.label): This is the text that appears in the -# context submenu to blackbox all files inside of the selected directory - -# LOCALIZATION NOTE (unblackBoxAllInDir.label): This is the text that appears in the -# context submenu to unblackbox all files inside of the selected directory - -# LOCALIZATION NOTE (blackBoxAllOutsideDir.label): This is the text that appears in the -# context submenu to blackbox all files outside of the selected directory - -# LOCALIZATION NOTE (unblackBoxAllOutsideDir.label: This is the text that appears in the -# context submenu to unblackbox all files outside of the selected directory - # LOCALIZATION NOTE (ignoreAll.label): Text associated with the ignore context menu item ignoreAll.label=Ignora @@ -561,18 +537,7 @@ # LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item # for pretty printing the source. - -# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated -# with the blackbox button - -# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated -# with the blackbox button - -# LOCALIZATION NOTE (blackboxContextItem.blackbox): Text associated -# with the blackbox context menu item - -# LOCALIZATION NOTE (blackboxContextItem.unblackbox): Text associated -# with the unblackbox context menu item +sourceTabs.prettyPrint=Mostra la font en un format intel·ligible # LOCALIZATION NOTE (sourceFooter.ignores): Tooltip text associated # with the ignores button @@ -586,6 +551,18 @@ # LOCALIZATION NOTE (ignoreContextItem.unignore): Text associated # with the unignore context menu item +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item + +# LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated +# with the ignore lines context menu item + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLines): Text associated +# with the unignore lines context menu item + # LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated # with a mapped source. %S is replaced by the source map origin. @@ -955,4 +932,3 @@ # service worker that is redundant. # LOCALIZATION NOTE (serviceWorkerInfo.unknown): State displayed for a # service worker that is in an unknown state. - diff -Nru thunderbird-91.7.0+build2/l10n/ca/devtools/client/jsonview.properties thunderbird-91.8.1+build1/l10n/ca/devtools/client/jsonview.properties --- thunderbird-91.7.0+build2/l10n/ca/devtools/client/jsonview.properties 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/devtools/client/jsonview.properties 2022-04-15 07:51:00.000000000 +0000 @@ -37,9 +37,8 @@ # LOCALIZATION NOTE (jsonViewer.PrettyPrint): Label for JSON # pretty print action button. -jsonViewer.PrettyPrint=Format d'impressió +jsonViewer.PrettyPrint=Mostra en un format intel·ligible # LOCALIZATION NOTE (jsonViewer.filterJSON): Label used in search box # at the top right cornder of the JSON Viewer. jsonViewer.filterJSON=Filtra JSON - diff -Nru thunderbird-91.7.0+build2/l10n/ca/devtools/client/performance.properties thunderbird-91.8.1+build1/l10n/ca/devtools/client/performance.properties --- thunderbird-91.7.0+build2/l10n/ca/devtools/client/performance.properties 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/devtools/client/performance.properties 2022-04-15 07:51:00.000000000 +0000 @@ -67,6 +67,8 @@ category.gc=GC category.network=Xarxa category.graphics=Gràfics +category.dom=DOM +category.idle=Inactiu category.tools=Eines # LOCALIZATION NOTE (table.bytes): diff -Nru thunderbird-91.7.0+build2/l10n/ca/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/ca/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/ca/devtools/client/toolbox-options.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/devtools/client/toolbox-options.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -10,19 +10,15 @@ # The heading options-select-default-tools-label = Eines per a desenvolupadors per defecte - # The label for the explanation of the * marker on a tool which is currently not supported # for the target of the toolbox. options-tool-not-supported-label = * No és compatible amb l'element actual de la caixa d'eines - # The label for the heading of group of checkboxes corresponding to the developer tools # added by add-ons. This heading is hidden when there is no developer tool installed by add-ons. options-select-additional-tools-label = Eines per a desenvolupadors instal·lades per complements - # The label for the heading of group of checkboxes corresponding to the default developer # tool buttons. options-select-enabled-toolbox-buttons-label = Botons de la caixa d'eines disponibles - # The label for the heading of the radiobox corresponding to the theme options-select-dev-tools-theme-label = Temes @@ -30,12 +26,10 @@ # The heading options-context-inspector = Inspector - # The label for the checkbox option to show user agent styles options-show-user-agent-styles-label = Mostra els estils del navegador options-show-user-agent-styles-tooltip = .title = En activar aquesta opció es mostraran els estils per defecte que ha carregat el navegador. - # The label for the checkbox option to enable collapse attributes options-collapse-attrs-label = Trunca els atributs DOM options-collapse-attrs-tooltip = @@ -54,7 +48,6 @@ # The heading options-styleeditor-label = Editor d'estils - # The label for the checkbox that toggles autocompletion of css in the Style Editor options-stylesheet-autocompletion-label = Autocompleta el CSS options-stylesheet-autocompletion-tooltip = @@ -64,7 +57,10 @@ # The heading options-screenshot-label = Comportament de la captura de pantalla - +# Label for the checkbox that toggles screenshot to clipboard feature +options-screenshot-clipboard-only-label = Desa la captura de pantalla només al porta-retalls +options-screenshot-clipboard-tooltip2 = + .title = Desa la captura de pantalla directament al porta-retalls # Label for the checkbox that toggles the camera shutter audio for screenshot tool options-screenshot-audio-label = Reprodueix un so d'obturador de càmera options-screenshot-audio-tooltip = @@ -74,7 +70,6 @@ # The heading options-sourceeditor-label = Preferències de l'editor - options-sourceeditor-detectindentation-tooltip = .title = Determina el sagnat en funció del contingut del codi font options-sourceeditor-detectindentation-label = Detecta el sagnat @@ -90,42 +85,34 @@ ## Advanced section -# The heading +# The heading (this item is also used in perftools.ftl) options-context-advanced-settings = Paràmetres avançats - # The label for the checkbox that toggles the HTTP cache on or off options-disable-http-cache-label = Inhabilita la memòria cau HTTP (quan la caixa d'eines està oberta) options-disable-http-cache-tooltip = .title = Activeu aquesta opció per inhabilitar la memòria cau HTTP per a totes les pestanyes que tinguin oberta la caixa d'eines. Aquesta opció no afecta els processos de treball de servei. - # The label for checkbox that toggles JavaScript on or off options-disable-javascript-label = Inhabilita el JavaScript * options-disable-javascript-tooltip = .title = Activeu aquesta opció per inhabilitar el JavaScript en la pestanya actual. Aquest paràmetre s'oblidarà quan tanqueu la pestanya o la caixa d'eines. - # The label for checkbox that toggles chrome debugging, i.e. the devtools.chrome.enabled preference options-enable-chrome-label = Habilita les caixes d'eines de depuració del chrome del navegador i complements options-enable-chrome-tooltip = .title = Activeu aquesta opció per permetre l'ús de diverses eines per a desenvolupadors en el context del navegador (mitjançant Eines > Desenvolupador web > Caixa d'eines) i depurar complements des del Gestor de complements - # The label for checkbox that toggles remote debugging, i.e. the devtools.debugger.remote-enabled preference options-enable-remote-label = Habilita la depuració remota options-enable-remote-tooltip2 = .title = Si activeu aquesta opció, podreu depurar aquesta instància del navegador remotament - # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Habilita els processos de treball de servei a través de HTTP (quan la caixa d'eines és oberta) options-enable-service-workers-http-tooltip = .title = Activeu aquesta opció per permetre els processos de treball de servei a través de HTTP en totes les pestanyes que tinguin la caixa d'eines oberta. - # The label for the checkbox that toggles source maps in all tools. options-source-maps-label = Habilita els mapes de fonts options-source-maps-tooltip = .title = Si habiliteu aquesta opció, es maparan les fonts en les eines. - # The message shown for settings that trigger page reload options-context-triggers-page-refresh = * Només la sessió actual, recarrega la pàgina - # The label for the checkbox that toggles the display of the platform data in the # Profiler i.e. devtools.profiler.ui.show-platform-data a boolean preference in about:config options-show-platform-data-label = Mostra dades de la plataforma Gecko diff -Nru thunderbird-91.7.0+build2/l10n/ca/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/ca/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/ca/devtools/client/webconsole.properties 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/devtools/client/webconsole.properties 2022-04-15 07:51:00.000000000 +0000 @@ -436,6 +436,7 @@ # LOCALIZATION NOTE (webconsole.editor.toolbar.prettyPrintButton.tooltip) # Label used for the tooltip on the prettyPrint button, in the editor toolbar, which is # displayed when the editor mode is enabled (devtools.webconsole.input.editor=true). +webconsole.editor.toolbar.prettyPrintButton.tooltip=Mostra l'expressió en un format intel·ligible # LOCALIZATION NOTE (webconsole.editor.toolbar.executeButton.tooltip) # Label used for the tooltip on the history previous expression, in the editor toolbar, diff -Nru thunderbird-91.7.0+build2/l10n/ca/devtools/shared/debugger-paused-reasons.ftl thunderbird-91.8.1+build1/l10n/ca/devtools/shared/debugger-paused-reasons.ftl --- thunderbird-91.7.0+build2/l10n/ca/devtools/shared/debugger-paused-reasons.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/devtools/shared/debugger-paused-reasons.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -1,3 +1,22 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +### These strings are used inside the Debugger which is available from the Web +### Developer sub-menu -> 'Debugger', as well as in the "Paused Debugger +### Overlay" that is displayed in the content page when it pauses. + + +### The correct localization of this file might be to keep it in +### English, or another language commonly spoken among web developers. +### You want to make that choice consistent across the developer tools. +### A good criteria is the language in which you'd find the best +### documentation on web development on the web. + +# The text that is displayed to describe an added node which triggers a subtree +# modification +whypaused-mutation-breakpoint-added = S'ha afegit: +# The text that is displayed to describe a removed node which triggers a subtree +# modification +whypaused-mutation-breakpoint-removed = S'ha eliminat: diff -Nru thunderbird-91.7.0+build2/l10n/ca/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/ca/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/ca/dom/chrome/dom/dom.properties 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/dom/chrome/dom/dom.properties 2022-04-15 07:51:00.000000000 +0000 @@ -33,7 +33,7 @@ FormValidationSelectMissing=Seleccioneu un element de la llista. FormValidationInvalidEmail=Introduïu una adreça electrònica. FormValidationInvalidURL=Introduïu un URL. -FormValidationInvalidDate =Introduïu una data vàlida. +FormValidationInvalidDate=Introduïu una data vàlida. FormValidationPatternMismatch=Feu que coincideixi amb el format sol·licitat. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Feu que coincideixi amb el format sol·licitat: %S. @@ -46,7 +46,7 @@ # LOCALIZATION NOTE (FormValidationDateTimeRangeUnderflow): %S is a date or a time. FormValidationDateTimeRangeUnderflow=Seleccioneu un valor que no sigui anterior a %S. # LOCALIZATION NOTE (FormValidationStepMismatch): both %S can be a number, a date or a time. -FormValidationStepMismatch=Seleccioneu un valor vàlid. Els dos valors vàlid més propers són %S i %S. +FormValidationStepMismatch=Seleccioneu un valor vàlid. Els dos valors vàlids més propers són %S i %S. # LOCALIZATION NOTE (FormValidationStepMismatchOneValue): %S can be a number, a date or a time. This is called instead of FormValidationStepMismatch when the second value is the same as the first. FormValidationStepMismatchOneValue=Seleccioneu un valor vàlid. El més proper és %S. # LOCALIZATION NOTE (FormValidationTimeReversedRangeUnderflowAndOverflow): %1$S,%2$S are time. @@ -261,7 +261,6 @@ GenericImageNamePNG=imatge.png GenericFileName=fitxer GeolocationInsecureRequestIsForbidden=Una sol·licitud de geolocalització només es pot satisfer en un context segur. -# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name. # LOCALIZATION NOTE: Do not translate "content", "Window", and "window.top" # LOCALIZATION NOTE: The first %S is the tag name of the element that starts the loop, the second %S is the element's ID. # LOCALIZATION NOTE: The first %S is the tag name of the element in the chain where the chain was broken, the second %S is the element's ID. @@ -282,6 +281,7 @@ #LOCALIZATION NOTE(DeprecatedTestingMethodWarning): Do not translate this message. It's just testing only. #LOCALIZATION NOTE(DeprecatedTestingAttributeWarning): Do not translate this message. It's just testing only. # LOCALIZATION NOTE (CreateImageBitmapCanvasRenderingContext2DWarning): Do not translate CanvasRenderingContext2D and createImageBitmap. +# LOCALIZATION NOTE (DrawWindowCanvasRenderingContext2DWarning): Do not translate CanvasRenderingContext2D, drawWindow and tabs.captureTab. # LOCALIZATION NOTE (MozRequestFullScreenDeprecatedPrefixWarning): Do not translate mozRequestFullScreen. # LOCALIZATION NOTE (MozfullscreenchangeDeprecatedPrefixWarning): Do not translate onmozfullscreenchange. # LOCALIZATION NOTE (MozfullscreenerrorDeprecatedPrefixWarning): Do not translate onmozfullscreenerror. @@ -312,4 +312,13 @@ # LOCALIZATION NOTE: %S is the name of the folder the user selected in the file picker. # LOCALIZATION NOTE: %S is the URL of the preload that was ignored. # LOCALIZATION NOTE: %S is the blob URL. Don't translate "agent cluster". +# LOCALIZATION NOTE: Do not translate "Element.setCapture()" and "Element.setPointerCapture()"". +# LOCALIZATION NOTE: Do not translate "Element.releaseCapture()" and "Element.releasePointerCapture()". +# LOCALIZATION NOTE: Do not translate "Document.releaseCapture()" and "Element.releasePointerCapture()". +# LOCALIZATION NOTE: Don't translate browser.runtime.lastError, %S is the error message from the unchecked value set on browser.runtime.lastError. + +# LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". + +# LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" +# LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" diff -Nru thunderbird-91.7.0+build2/l10n/ca/security/manager/security/certificates/certManager.ftl thunderbird-91.8.1+build1/l10n/ca/security/manager/security/certificates/certManager.ftl --- thunderbird-91.7.0+build2/l10n/ca/security/manager/security/certificates/certManager.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/security/manager/security/certificates/certManager.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -4,131 +4,94 @@ certmgr-title = .title = Gestor de certificats - certmgr-tab-mine = .label = Els vostres certificats - certmgr-tab-remembered = .label = Decisions d'autenticació - certmgr-tab-people = .label = D'altri - certmgr-tab-servers = .label = Servidors - certmgr-tab-ca = .label = Entitats - certmgr-mine = Teniu certificats d'aquestes organitzacions que us identifiquen certmgr-remembered = Aquests certificats s'utilitzen per identificar-vos en els llocs web certmgr-people = Teniu certificats al fitxer que identifiquen aquesta gent certmgr-server = Aquestes entrades identifiquen les excepcions d'error de certificats de servidor certmgr-ca = Teniu certificats al fitxer que identifiquen aquestes entitats certificadores - certmgr-edit-ca-cert = .title = Edita els paràmetres de confiança del certificat de la CA .style = width: 48em; - certmgr-edit-cert-edit-trust = Edita els paràmetres de confiança: - certmgr-edit-cert-trust-ssl = .label = Aquest certificat pot identificar llocs web. - certmgr-edit-cert-trust-email = .label = Aquest certificat pot identificar usuaris de correu. - certmgr-delete-cert = .title = Suprimeix el certificat .style = width: 48em; height: 24em; - certmgr-cert-host = .label = Amfitrió - certmgr-cert-name = .label = Nom del certificat - certmgr-cert-server = .label = Servidor - certmgr-override-lifetime = .label = Temps de vida - certmgr-token-name = .label = Dispositiu de seguretat - certmgr-begins-label = .label = Data d'inici - certmgr-expires-label = .label = Data de venciment - certmgr-email = .label = Adreça electrònica - certmgr-serial = .label = Número de sèrie - certmgr-view = .label = Visualitza… .accesskey = V - certmgr-edit = .label = Edita la confiança… .accesskey = E - certmgr-export = .label = Exporta… .accesskey = x - certmgr-delete = .label = Suprimeix… .accesskey = x - certmgr-delete-builtin = .label = Suprimeix o deixa de confiar-hi… .accesskey = d - certmgr-backup = .label = Fes-ne còpia de seguretat… .accesskey = p - certmgr-backup-all = .label = Fes-ne còpia de seguretat de tot… .accesskey = g - certmgr-restore = .label = Importa… .accesskey = m - certmgr-add-exception = .label = Afegeix una excepció… .accesskey = x - exception-mgr = .title = Afegeix una excepció de seguretat - exception-mgr-extra-button = .label = Confirma l'excepció de seguretat .accesskey = C - exception-mgr-supplemental-warning = Bancs, botigues i altres llocs públics legítims no us demanaran que ho feu. - exception-mgr-cert-location-url = .value = Ubicació: - exception-mgr-cert-location-download = .label = Obtén el certificat .accesskey = b - exception-mgr-cert-status-view-cert = .label = Visualitza… .accesskey = V - exception-mgr-permanent = .label = Emmagatzema permanentment aquesta excepció .accesskey = p - pk11-bad-password = La contrasenya no és correcta. pkcs12-decode-err = No s'ha pogut descodificar el fitxer. Pot ser que no estigui en format PKCS #12, que estigui malmès, o que la contrasenya que heu introduït sigui incorrecta. pkcs12-unknown-err-restore = No s'ha pogut restaurar el fitxer PKCS #12 per raons desconegudes. @@ -161,38 +124,30 @@ .title = Suprimeix els vostres certificats delete-user-cert-confirm = Esteu segur que voleu suprimir aquests certificats? delete-user-cert-impact = Si suprimiu un dels propis certificats, no podreu utilitzar-lo més per identificar-vos. - - delete-ssl-override-title = .title = Suprimeix l'excepció de certificats de servidor delete-ssl-override-confirm = Segur que voleu suprimir aquesta excepció de servidor? delete-ssl-override-impact = Si suprimiu una excepció de servidor, es restauraran les comprovacions de seguretat habituals per al servidor i us caldrà utilitzar un certificat vàlid. - delete-ca-cert-title = .title = Suprimeix o deixa de confiar en els certificats de la CA delete-ca-cert-confirm = Esteu segur que voleu suprimir aquests certificats de la CA? En el cas de certificats integrats, se n'eliminarà tota la confiança, que té el mateix efecte. Esteu segur que voleu suprimir-los o deixar-hi de confiar? delete-ca-cert-impact = Si suprimiu o deixeu de confiar en un certificat d'una entitat certificadora (CA), l'aplicació deixarà de confiar en els certificats que emeti aquella CA. - - delete-email-cert-title = .title = Suprimeix els certificats de correu electrònic delete-email-cert-confirm = Esteu segur que voleu suprimir aquests certificats de correu electrònic d'aquestes persones? delete-email-cert-impact = Si suprimiu un certificat de correu electrònic d'algú, ja no podreu enviar-li correu xifrat. - # Used for semi-uniquely representing a cert. # # Variables: # $serialNumber : the serial number of the cert in AA:BB:CC hex format. cert-with-serial = .value = Certificat amb número de sèrie: { $serialNumber } - -## Cert Viewer - # Used to indicate that the user chose not to send a client authentication certificate to a server that requested one in a TLS handshake. send-no-client-certificate = No enviïs cap certificat de client - # Used when no cert is stored for an override no-cert-stored-for-override = (No emmagatzemat) +# When a certificate is unavailable (for example, it has been deleted or the token it exists on has been removed). +certificate-not-available = (No disponible) ## Used to show whether an override is temporary or permanent diff -Nru thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/aboutAddons.ftl thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/aboutAddons.ftl --- thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/aboutAddons.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/aboutAddons.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -9,6 +9,8 @@ search-header-shortcut = .key = f list-empty-get-extensions-message = Obteniu més extensions i temes a { $domain } +list-empty-get-dictionaries-message = Obteniu més diccionaris a { $domain } +list-empty-get-language-packs-message = Obteniu més paquets d’idioma a { $domain } list-empty-installed = .value = No teniu instal·lat cap complement d'aquest tipus list-empty-available-updates = diff -Nru thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/aboutProcesses.ftl thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/aboutProcesses.ftl --- thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/aboutProcesses.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/aboutProcesses.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -25,7 +25,9 @@ about-processes-browser-process = { -brand-short-name } ({ $pid }) about-processes-file-process = Fitxers ({ $pid }) +about-processes-extension-process = Extensions ({ $pid }) about-processes-gpu-process = GPU ({ $pid }) +about-processes-socket-process = Xarxa ({ $pid }) ## Isolated process names ## Variables: @@ -35,6 +37,10 @@ ## Details within processes +# Tab +# Variables: +# $name (String) The name of the tab (typically the title of the page, might be the url while the page is loading). +about-processes-tab-name = Pestanya: { $name } ## Displaying CPU (percentage and total) ## Variables: @@ -45,6 +51,11 @@ ## $unit (String) The unit in which to display $total. See the definitions ## of `duration-unit-*`. +# Special case: data is not available yet. +about-processes-cpu-user-and-kernel-not-ready = (s'està mesurant) +# Special case: process or thread is currently idle. +about-processes-cpu-idle = inactiu + .title = Temps total de la CPU: { NUMBER($total, maximumFractionDigits: 2) } { $unit } ## Displaying Memory (total and delta) ## Variables: @@ -62,6 +73,14 @@ ## Duration units +duration-unit-h = h +duration-unit-d = d ## Memory units +memory-unit-KB = kB +memory-unit-MB = MB +memory-unit-GB = GB +memory-unit-TB = TB +memory-unit-PB = PB +memory-unit-EB = EB diff -Nru thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/aboutThirdParty.ftl thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/aboutThirdParty.ftl --- thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/aboutThirdParty.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/aboutThirdParty.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -2,3 +2,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +third-party-button-open = + .title = Obre la ubicació del fitxer… +third-party-button-expand = + .title = Mostra la informació detallada +third-party-button-collapse = + .title = Amaga la informació detallada diff -Nru thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/abuseReports.ftl thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/abuseReports.ftl --- thunderbird-91.7.0+build2/l10n/ca/toolkit/toolkit/about/abuseReports.ftl 2022-03-07 21:36:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/ca/toolkit/toolkit/about/abuseReports.ftl 2022-04-15 07:51:00.000000000 +0000 @@ -2,26 +2,21 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Localized string used as the dialog window title (a new behavior locked -# behind the "extensions.abuseReport.openDialog" preference). +# Localized string used as the dialog window title. # "Report" is a noun in this case, "Report for AddonName". # # Variables: # $addon-name (string) - Name of the add-on being reported abuse-report-dialog-title = Informe sobre { $addon-name } - abuse-report-title-extension = Informeu sobre aquesta extensió a { -vendor-short-name } abuse-report-title-theme = Informeu sobre aquest tema a { -vendor-short-name } abuse-report-subtitle = Quin és el problema? - # Variables: # $author-name (string) - Name of the add-on author abuse-report-addon-authored-by = per { $author-name } - abuse-report-learnmore = No saps quin problema seleccionar? Més informació sobre com informar sobre les extensions i els temes - abuse-report-submit-description = Descriviu el problema (opcional) abuse-report-textarea = .placeholder = Ens resulta més fàcil resoldre un problema si en tenim els detalls. Descriviu allò que us passa. Gràcies per ajudar-nos a mantenir Internet en bon estat de salut. @@ -37,12 +32,6 @@ abuse-report-submit-button = Envia ## Message bars descriptions. - - -## Variables: -## $addon-name (string) - Name of the add-on - -## Message bars descriptions. ## ## Variables: ## $addon-name (string) - Name of the add-on @@ -60,6 +49,8 @@ abuse-report-messagebar-action-remove-extension = Sí, elimina-la abuse-report-messagebar-action-keep-extension = No, mantén-la +abuse-report-messagebar-action-remove-sitepermission = Sí, elimina'l +abuse-report-messagebar-action-keep-sitepermission = No, mantén-lo abuse-report-messagebar-action-remove-theme = Sí, elimina'l abuse-report-messagebar-action-keep-theme = No, mantén-lo abuse-report-messagebar-action-retry = Reintenta @@ -69,19 +60,16 @@ abuse-report-damage-reason-v2 = Ha malmès l'ordinador o ha posat les meves dades en risc abuse-report-damage-example = Exemple: programari maliciós injectat o robatori de dades - abuse-report-spam-reason-v2 = Conté brossa o insereix publicitat no desitjada abuse-report-spam-example = Exemple: insereix anuncis en les pàgines web - abuse-report-settings-reason-v2 = Ha canviat el meu motor de cerca, la pàgina d'inici o la de pestanya nova sense informar-me'n ni preguntar-m'ho abuse-report-settings-suggestions = Abans d’informar sobre l'extensió, podeu provar de canviar els paràmetres: abuse-report-settings-suggestions-search = Canvieu els paràmetres de cerca per defecte abuse-report-settings-suggestions-homepage = Canvieu la vostra pàgina principal i de pestanya nova - abuse-report-deceptive-reason-v2 = Pretén ser quelcom que no és abuse-report-deceptive-example = Exemple: imatges o descripcions enganyoses - abuse-report-broken-reason-extension-v2 = No funciona, deixa llocs web inutilitzables o fa que el { -brand-product-name } vagi lent +abuse-report-broken-reason-sitepermission-v2 = No funciona, deixa llocs web inutilitzables o fa que el { -brand-product-name } vagi lent abuse-report-broken-reason-theme-v2 = No funciona o fa que el navegador es vegi malament abuse-report-broken-example = Exemple: les funcions són lentes, difícils d’utilitzar o no funcionen; parts dels llocs web no es carreguen o tenen un aspecte inusual abuse-report-broken-suggestions-extension = @@ -90,15 +78,11 @@ abuse-report-broken-suggestions-theme = Sembla que heu identificat un error. A més d'enviar un informe aquí, la millor manera de resoldre un problema de funcionalitat és contactar amb el desenvolupador del tema. Visiteu el lloc web del tema per obtenir la informació del desenvolupador. - abuse-report-policy-reason-v2 = Inclou contingut d'odi, violent o il·legal abuse-report-policy-suggestions = Nota: els problemes de propietat intel·lectual i de marca s'han de notificar en un procés independent. Utilitzeu aquestes instruccions per informar del problema. - abuse-report-unwanted-reason-v2 = No l'he volgut mai i no sé com desfer-me'n abuse-report-unwanted-example = Exemple: una aplicació la va instal·lar sense el meu permís - abuse-report-other-reason = Una altra cosa - diff -Nru thunderbird-91.7.0+build2/l10n/cs/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/cs/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/cs/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Soukromí: Soukromá událost calendar-editable-item-privacy-icon-confidential = .alt = Soukromí: Zobrazit pouze datum a čas +calendar-editable-item-recurrence = + .alt = Opakování +calendar-editable-item-recurrence-exception = + .alt = Výjimka z opakování calendar-editable-item-todo-icon-task = .alt = Úkol calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/cs/chat/matrix.properties thunderbird-91.8.1+build1/l10n/cs/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/cs/chat/matrix.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/chat/matrix.properties 2022-04-15 07:51:17.000000000 +0000 @@ -242,3 +242,15 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=Uživatel %1$S zrušil požadavek na ověření z důvodu: %2$S message.verification.done=Ověření dokončeno. +message.decryptionError=Obsah této zprávy se nepodařilo dešifrovat. Pro opětovné vyžádání šifrovacích klíčů z ostatních zařízení klepněte pravým tlačítkem na tuto zprávu. +message.decrypting=Probíhá dešifrování… +message.redacted=Zpráva byla redigována. + +# Label in the message context menu +message.action.requestKey=Znovu vyžádat klíče +message.action.redact=Redigovat +message.action.report=Nahlásit zprávu + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Při odesílání vaší zprávy „%1$S“ došlo k chybě. diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/accessibility.ftl thunderbird-91.8.1+build1/l10n/cs/devtools/client/accessibility.ftl --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/accessibility.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/accessibility.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -6,19 +6,15 @@ ### These strings are used inside the Accessibility panel. accessibility-learn-more = Zjistit více - accessibility-text-label-header = Textové popisky a názvy - accessibility-keyboard-header = Klávesnice ## Text entries that are used as text alternative for icons that depict accessibility isses. accessibility-warning = .alt = Varování - accessibility-fail = .alt = Chyba - accessibility-best-practices = .alt = Osvědčené postupy @@ -27,39 +23,22 @@ ## with its text label or accessible name. accessibility-text-label-issue-area = K označení prvků
oblasti
, které mají atribut href, použijte atribut alt. Zjistit více - accessibility-text-label-issue-dialog = Dialogy by měly být označeny. Zjistit více - accessibility-text-label-issue-document-title = Dokumenty musí mít title. Zjistit více - accessibility-text-label-issue-embed = Vložený obsah musí být označen. Zjistit více - accessibility-text-label-issue-figure = Obrázky s volitelnými titulky by měly být označeny štítkem. Zjistit více - accessibility-text-label-issue-fieldset = Prvky fieldset musí být označeny. Zjistit více - accessibility-text-label-issue-fieldset-legend2 = Prvek fieldset označte pomocí legend. Zjistit více - accessibility-text-label-issue-form = Prvky formuláře musí být označeny. Zjistit více - accessibility-text-label-issue-form-visible = Prvky formuláře by měly mít viditelný textový popisek. Zjistit více - accessibility-text-label-issue-frame = Prvky frame musí být označeny. Zjistit více - accessibility-text-label-issue-glyph = Použijte atribut alt k označení prvků mglyph. Zjistit více - accessibility-text-label-issue-heading = Nadpisy musí být označeny. Zjistit více - accessibility-text-label-issue-heading-content = Nadpisy by měly mít viditelný textový obsah. Zjistit více - accessibility-text-label-issue-iframe = Použijte atribut title k popisu obsahu iframe. Zjistit více - accessibility-text-label-issue-image = Obsah s obrázky musí být označen. Zjistit více - accessibility-text-label-issue-interactive = Interaktivní prvky musí být označeny. Zjistit více - accessibility-text-label-issue-optgroup-label2 = Prvek optgroup označte atributem label. Zjistit více - accessibility-text-label-issue-toolbar = Panely nástrojů musí být označeny, pokud existuje více než jeden panel nástrojů. Zjistit více ## Text entries for a paragraph used in the accessibility panel sidebar's checks section @@ -67,4 +46,7 @@ ## issue. accessibility-keyboard-issue-semantics = Prvky dosažitelné pomocí klávesnice by měly mít interaktivní sémantiku. Zjistit více - +accessibility-keyboard-issue-tabindex = Vyhněte se používaní atributu tabindex s hodnotou větší než nula. Zjistit více +accessibility-keyboard-issue-action = Interaktivní prvky musí být možno aktivovat klávesnicí. Zjistit více +accessibility-keyboard-issue-focusable = Interaktivní prvky musí být přístupné klávesnicí. Zjistit více +accessibility-keyboard-issue-mouse-only = Prvky, na které lze kliknout, musí být dosažitelné pomocí klávesnice, a měly by mít interaktivní sémantiku. Zjistit více diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/accessibility.properties thunderbird-91.8.1+build1/l10n/cs/devtools/client/accessibility.properties --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/accessibility.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/accessibility.properties 2022-04-15 07:51:15.000000000 +0000 @@ -211,6 +211,7 @@ # for the badge tooltip that is rendered on mouse hover over the badge in the # accessible row in the accessibility tree for a given accessible object that # does not satisfy the WCAG guideline for keyboard accessibility. +accessibility.badge.keyboard.tooltip=Nesplňuje standardy WCAG pro dostupnost klávesnicí. # LOCALIZATION NOTE (accessibility.badge.textLabel.tooltip): A title text # for the badge tooltip that is rendered on mouse hover over the badge in the @@ -248,6 +249,7 @@ # LOCALIZATION NOTE (accessibility.pref.scroll.into.view.title): A title # text for the tooltip for the checkbox pref in the accessibility panel that # sets node auto scroll. +accessibility.pref.scroll.into.view.title=Automaticky posouvat vybraný uzel do zobrazení # LOCALIZATION NOTE (accessibility.pref.scroll.into.view.label): A title # text for the checkbox pref in the accessibility panel that sets node auto @@ -287,8 +289,8 @@ # LOCALIZATION NOTE (accessibility.toolbar.displayTabbingOrder.label): A title text for a checkbox label # in the accessibility panel toolbar that turns on/off the overlay of focusable elements in their # tabbing order. +accessibility.toolbar.displayTabbingOrder.label=Zobrazit pořadí pro navigaci tabulátorem # LOCALIZATION NOTE (accessibility.toolbar.displayTabbingOrder.tooltip): A title text for a checkbox # tooltip in the accessibility panel toolbar that turns on/off the overlay of focusable elements in # their tabbing order. - diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/application.ftl thunderbird-91.8.1+build1/l10n/cs/devtools/client/application.ftl --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/application.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/application.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -42,8 +42,13 @@ serviceworker-worker-status-running = Běžící # Service Worker status. A stopped service worker is registered but not currently active. serviceworker-worker-status-stopped = Zastavený +# Text displayed when no service workers are visible for the current page. +serviceworker-empty-intro2 = Nenalezen žádný service worker # Link will open https://developer.mozilla.org/docs/Web/API/Service_Worker_API/Using_Service_Workers serviceworker-empty-intro-link = Zjistit více +# Suggestion to go to about:debugging in order to see Service Workers for all domains. +# Link will open about:debugging in a new tab. +serviceworker-empty-suggestions-aboutdebugging2 = Zobrazit service workery z jiných domén # Header for the Manifest page when we have an actual manifest manifest-view-header = Manifest aplikace # Header for the Manifest page when there's no manifest to inspect diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/cs/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/compatibility.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/compatibility.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -43,7 +43,14 @@ [few] { $number } výskyty *[other] { $number } výskytů } - compatibility-no-issues-found = Nebyly nalezeny žádné problémy s kompatibilitou. compatibility-close-settings-button = .title = Zavřít nastavení +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Problémy s kompatibilitou v: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/components.properties thunderbird-91.8.1+build1/l10n/cs/devtools/client/components.properties --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/components.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/components.properties 2022-04-15 07:51:15.000000000 +0000 @@ -22,3 +22,15 @@ # LOCALIZATION NOTE (notificationBox.closeTooltip): The content of a tooltip that # appears when hovering over the close button in a notification box. notificationBox.closeTooltip=Zavře tuto zprávu + +# LOCALIZATION NOTE (appErrorBoundary.description): This is the information displayed +# once the panel errors. +# %S represents the name of panel which has the crash. +appErrorBoundary.description=Panel %S spadl. + +# LOCALIZATION NOTE (appErrorBoundary.fileBugButton): This is the text that appears in +# the button to visit the bug filing link. +appErrorBoundary.fileBugButton=Nahlásit chybu + +# LOCALIZATION NOTE (appErrorBoundary.reloadPanelInfo): This is the text that appears +# after the panel errors to instruct the user to reload the panel. diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/cs/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/debugger.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/debugger.properties 2022-04-15 07:51:15.000000000 +0000 @@ -314,6 +314,7 @@ breakpointMenuItem.disableSelf2.accesskey=Z breakpointMenuItem.deleteSelf2.label=Odebrat breakpointMenuItem.deleteSelf2.accesskey=r +breakpointMenuItem.disabledbg.label=Nikdy zde nepřerušovat breakpointMenuItem.enabledbg.label=Pozastavit zde breakpointMenuItem.enableOthers2.label=Povolit ostatní breakpointMenuItem.enableOthers2.accesskey=o @@ -344,6 +345,7 @@ breakpointMenuItem.deleteAll=Odebrat všechny zarážky breakpointMenuItem.disableAllAtLine.label=Zakázat zarážky na řádku breakpointMenuItem.enableAllAtLine.label=Povolit zarážky na řádku +breakpointMenuItem.removeAllAtLine.label=Odebrat zarážku na řádce # LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header. breakpoints.header=Zarážky @@ -483,23 +485,30 @@ # LOCALIZATION NOTE (editorWrapping.show.label): Context menu item # for showing the wrap lines block +editorWrapping.show.label=Zalamovat řádky # LOCALIZATION NOTE (editorWrapping.hide.label): Context menu item # for showing the wrap lines block +editorWrapping.hide.label=Nezalamovat řádky # LOCALIZATION NOTE (editorWrapping.toggle.label): Context menu item # label for toggling the lines wrapping feature +editorWrapping.toggle.label=Zalamovat řádky # LOCALIZATION NOTE (editorWrapping.toggle.tooltip): Context menu item # tooltip for toggling the lines wrapping feature +editorWrapping.toggle.tooltip=Zalamování řádků v editoru debuggeru # LOCALIZATION NOTE (settings.button.label): Label for Settings button +settings.button.label=Nastavení debuggeru # LOCALIZATION NOTE (settings.disableJavaScript.label): Context menu item # label for disabling JavaScript +settings.disableJavaScript.label=Zakázat JavaScript # LOCALIZATION NOTE (settings.disableJavaScript.tooltip): Context menu item # tooltip for disabling JavaScript +settings.disableJavaScript.tooltip=Zakáže JavaScript (vyžaduje opětovné načtení stránky) # LOCALIZATION NOTE (settings.toggleSourceMaps.tooltip): Context menu item # tooltip for toggling the source maps feature @@ -601,15 +610,41 @@ # LOCALIZATION NOTE (sourceFooter.ignores): Tooltip text associated # with the ignores button +sourceFooter.ignore=Ignorovat zdroj # LOCALIZATION NOTE (sourceFooter.unignore): Tooltip text associated # with the ignore button +sourceFooter.unignore=Neignorovat zdroj # LOCALIZATION NOTE (ignoreContextItem.ignore): Text associated # with the ignore context menu item +ignoreContextItem.ignore=Ignorovat zdroj +ignoreContextItem.ignore.accesskey=I # LOCALIZATION NOTE (ignoreContextItem.unignore): Text associated # with the unignore context menu item +ignoreContextItem.unignore=Neignorovat zdroj +ignoreContextItem.unignore.accesskey=N + +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Ignorovat řádek +ignoreContextItem.ignoreLine.accesskey=l + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Neignorovat řádek +ignoreContextItem.unignoreLine.accesskey=n + +# LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated +# with the ignore lines context menu item +ignoreContextItem.ignoreLines=Ignorovat řádky +ignoreContextItem.ignoreLines.accesskey=i + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLines): Text associated +# with the unignore lines context menu item +ignoreContextItem.unignoreLines=Neignorovat řádky +ignoreContextItem.unignoreLines.accesskey=n # LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated # with a mapped source. %S is replaced by the source map origin. @@ -655,6 +690,7 @@ eventlisteners.log.label=Zaznamenávat události do konzole # LOCALIZATION NOTE (eventlisteners.log): Checkbox label for logging events +eventlisteners.log=Protokol # LOCALIZATION NOTE (scopes.helpTooltip.label): Scopes right sidebar pane # icon tooltip for link to MDN @@ -819,13 +855,16 @@ # LOCALIZATION NOTE (whyPaused.mutationBreakpointAdded): The text that # is displayed to describe an added node which triggers a subtree modification +whyPaused.mutationBreakpointAdded=Přidáno: # LOCALIZATION NOTE (whyPaused.mutationBreakpointRemoved): The text that # is displayed to describe a removed node which triggers a subtree modification +whyPaused.mutationBreakpointRemoved=Odebráno: # LOCALIZATION NOTE (whyPaused.interrupted): The text that is displayed # in a info block explaining how the debugger is currently paused at # a JS execution +whyPaused.interrupted=Pozastaveno při provádění # LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed # in a info block explaining how the debugger is currently paused while stepping @@ -844,6 +883,7 @@ # LOCALIZATION NOTE (whyPaused.XHR): The text that is displayed # in a info block explaining how the debugger is currently paused on an # xml http request +whyPaused.XHR=Pozastaveno na XMLHttpRequest # LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed # in a info block explaining how the debugger is currently paused on a @@ -893,6 +933,7 @@ # LOCALIZATION NOTE (shortcuts.toggleCondPanel.breakpoint): text describing # keyboard shortcut action for toggling conditional panel for breakpoints +shortcuts.toggleCondPanel.breakpoint=Upravit podmíněnou zarážku # LOCALIZATION NOTE (shortcuts.toggleCondPanel.logPoint): text describing # keyboard shortcut action for toggling conditional panel for log points @@ -1016,14 +1057,19 @@ # worker that has been parsed. # LOCALIZATION NOTE (serviceWorkerInfo.installing): State displayed for a # service worker that is being installed. +serviceWorkerInfo.installing=instalace # LOCALIZATION NOTE (serviceWorkerInfo.installed): State displayed for a # service worker that has finished being installed. +serviceWorkerInfo.installed=nainstalován # LOCALIZATION NOTE (serviceWorkerInfo.activating): State displayed for a # service worker that is being activated. +serviceWorkerInfo.activating=aktivace # LOCALIZATION NOTE (serviceWorkerInfo.activated): State displayed for a # service worker that has finished being activated. +serviceWorkerInfo.activated=aktivován # LOCALIZATION NOTE (serviceWorkerInfo.redundant): State displayed for a # service worker that is redundant. +serviceWorkerInfo.redundant=nadbytečný # LOCALIZATION NOTE (serviceWorkerInfo.unknown): State displayed for a # service worker that is in an unknown state. - +serviceWorkerInfo.unknown=neznámý stav diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/inspector.properties thunderbird-91.8.1+build1/l10n/cs/devtools/client/inspector.properties --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/inspector.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/inspector.properties 2022-04-15 07:51:17.000000000 +0000 @@ -182,7 +182,9 @@ # LOCALIZATION NOTE (inspectorHTMLEdit.label): This is the label shown # in the inspector contextual-menu for the item that lets users edit the # (outer) HTML of the current node +inspectorXMLEdit.label=Upravit jako XML inspectorHTMLEdit.label=Upravit jako HTML +inspectorSVGEdit.label=Upravit jako SVG inspectorHTMLEdit.accesskey=U # LOCALIZATION NOTE (inspectorCopyInnerHTML.label): This is the label shown @@ -280,6 +282,7 @@ # LOCALIZATION NOTE (inspectorPseudoClassSubmenu.label): This is the label # shown in the inspector contextual-menu for the sub-menu of the pseudo-classes. +inspectorPseudoClassSubmenu.label=Změnit pseudo-třídu # LOCALIZATION NOTE (inspectorBreakpointSubmenu.label): This is the label # shown in the inspector contextual-menu for the sub-menu of the DOM breakpoints. diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/cs/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/netmonitor.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/netmonitor.properties 2022-04-15 07:51:17.000000000 +0000 @@ -63,6 +63,7 @@ # LOCALIZATION NOTE (allTabsMenuButton.tooltip): The tooltip that gets # displayed when hovering over the tabs overflow button. +allTabsMenuButton.tooltip=Zobrazit všechny panely # LOCALIZATION NOTE (headersEmptyText): This is the text displayed in the # headers tab of the network details pane when there are no headers available. @@ -74,6 +75,7 @@ # LOCALIZATION NOTE (messagesEmptyText): This is the text displayed in the # WebSockets tab of the network details pane when there are no frames available. +messagesEmptyText=Žádné zprávy pro tento dotaz # LOCALIZATION NOTE (cookiesEmptyText): This is the text displayed in the # cookies tab of the network details pane when there are no cookies available. @@ -88,6 +90,9 @@ # available for shown. responseEmptyText=Pro tento požadavek nejsou k dispozici žádné údaje o odpovědi +# LOCALIZATION NOTE (paramsNoPayloadText): This is the text displayed in the +# request tab of the network details pane when there are no params available. + # LOCALIZATION NOTE (paramsFilterText): This is the text displayed in the # request tab of the network details pane for the filtering input. paramsFilterText=Filtr parametrů požadavku @@ -104,6 +109,10 @@ # in the network details request tab identifying the request payload. paramsPostPayload=Obsah požadavku +# LOCALIZATION NOTE (netmonitor.request.raw): This is the label displayed +# on the button in the network details request tab that toggles the +# view of the network request between the raw data and the formatted display. + # LOCALIZATION NOTE (requestHeaders): This is the label displayed # in the network details headers tab identifying the request headers. requestHeaders=Hlavičky požadavku @@ -129,6 +138,14 @@ # in the network details response tab identifying the response payload. responsePayload=Obsah odpovědi +# LOCALIZATION NOTE (netmonitor.response.raw): This is the label displayed +# on the button in the network details response tab that toggles the +# view of the network response between the raw data and the formatted display. + +# LOCALIZATION NOTE (netmonitor.response.html): This is the text displayed +# in the response tab of the network details pane for an HTML preview. +netmonitor.response.html=HTML + # LOCALIZATION NOTE (jsonFilterText): This is the text displayed # in the response tab of the network details pane for the JSON filtering input. jsonFilterText=Filtr vlastností @@ -141,6 +158,10 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -207,9 +228,11 @@ # LOCALIZATION NOTE (networkMenu.ws.summary.framesCount2): This label is displayed # in the messages table footer providing the number of frames # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals +networkMenu.ws.summary.framesCount2=#1 zpráva;#1 zprávy;#1 zpráv # LOCALIZATION NOTE (networkMenu.ws.summary.framesCountEmpty): This label is displayed # in the messages table footer when there are no frames +networkMenu.ws.summary.framesCountEmpty=Žádné zprávy # LOCALIZATION NOTE (networkMenu.ws.summary.tooltip.framesCount): A tooltip explaining # what the framesCount label displays @@ -667,6 +690,7 @@ # LOCALIZATION NOTE (netmonitor.ws.toolbar.filterFreetext.key): This is the # shortcut key to focus on the messages panel toolbar messages filtering textbox +netmonitor.ws.toolbar.filterFreetext.key=CmdOrCtrl+E # LOCALIZATION NOTE (netmonitor.ws.toolbar.resetColumns): This is the label # displayed in the messages panel table header context menu. @@ -729,9 +753,11 @@ # LOCALIZATION NOTE (netmonitor.search.toolbar.caseSensitive): This is the label # displayed in the search toolbar to do a case sensitive search. +netmonitor.search.toolbar.caseSensitive=Rozlišovat velikost písmen # LOCALIZATION NOTE (netmonitor.search.status.labels.fetching): This is the label # displayed in the search results status bar when status is set to fetching. +netmonitor.search.status.labels.fetching=Vyhledávání… # LOCALIZATION NOTE (netmonitor.search.status.labels.canceled): This is the label # displayed in the search results status bar when status is set to cancelled. @@ -781,13 +807,18 @@ # LOCALIZATION NOTE (netmonitor.requestBlockingMenu.enableAllBlockedUrls): This is the # context menu item for enabling all blocked URLs +netmonitor.requestBlockingMenu.enableAllBlockedUrls=Povolit vše # LOCALIZATION NOTE (netmonitor.requestBlockingMenu.disableAllBlockedUrls): This is the # context menu item for disabling all blocked URLs +netmonitor.requestBlockingMenu.disableAllBlockedUrls=Zakázat vše # LOCALIZATION NOTE (netmonitor.actionbar.search): This is the label displayed # in the action bar's search tab +# LOCALIZATION NOTE (netmonitor.actionbar.HTTPCustomRequest): This is the label displayed +# in the action bar's edit and resend tab + # LOCALIZATION NOTE (messagesTruncated): This is the text displayed # in the messages panel when the number of messages is over the # truncation limit. @@ -808,6 +839,7 @@ # LOCALIZATION NOTE (netmonitor.tab.messages): This is the label displayed # in the network details pane identifying the messages tab. +netmonitor.tab.messages=Zprávy # LOCALIZATION NOTE (netmonitor.tab.cookies): This is the label displayed # in the network details pane identifying the cookies tab. @@ -823,6 +855,7 @@ # LOCALIZATION NOTE (netmonitor.tab.request): This is the label displayed # in the network details pane identifying the request tab. +netmonitor.tab.request=Požadavek # LOCALIZATION NOTE (netmonitor.tab.response): This is the label displayed # in the network details pane identifying the response tab. @@ -894,9 +927,11 @@ # LOCALIZATION NOTE (netmonitor.toolbar.search.key): This is the # shortcut key to toggle the search panel +netmonitor.toolbar.search.key=CmdOrCtrl+Shift+F # LOCALIZATION NOTE (netmonitor.toolbar.copy.key): This is the # shortcut key to copy a selected request url from the network table +netmonitor.toolbar.copy.key=CmdOrCtrl+C # LOCALIZATION NOTE (netmonitor.toolbar.filterFreetext.learnMore): This is # the title used for MDN icon in filtering textbox @@ -928,6 +963,11 @@ # LOCALIZATION NOTE (netmonitor.toolbar.search): This is the tooltip label displayed # in the network toolbar for the search button. +netmonitor.toolbar.search=Hledat + +# LOCALIZATION NOTE (netmonitor.toolbar.HTTPCustomRequest): This is the tooltip label displayed +# in the network toolbar for the new HTTP Custom Request button. +netmonitor.toolbar.HTTPCustomRequest=Nový požadavek # LOCALIZATION NOTE (netmonitor.toolbar.resetColumns): This is the label # displayed in the network table header context menu. @@ -939,6 +979,7 @@ # LOCALIZATION NOTE (netmonitor.toolbar.resizeColumnToFitContent): This is the label # displayed in the network table header context menu to resize a column to fit its content +netmonitor.toolbar.resizeColumnToFitContent=Změnit velikost sloupce podle obsahu # LOCALIZATION NOTE (netmonitor.toolbar.resizeColumnToFitContent.title): This is the title # tooltip displayed when draggable resizer in network table headers is hovered @@ -955,6 +996,7 @@ # LOCALIZATION NOTE (netmonitor.headers.toolbar.block): This is the # label displayed in the network details headers tab identifying the # block url toolbar button. +netmonitor.headers.toolbar.block=Blokovat # LOCALIZATION NOTE (netmonitor.headers.address): This is the label displayed # in the network details headers tab identifying the remote address. @@ -996,8 +1038,15 @@ # on the button in the headers tab that toggle view for raw request/response headers # from the currently displayed request +# LOCALIZATION NOTE (netmonitor.headers.blockedByCORS): This is the message displayed +# in the notification shown when a request has been blocked by CORS with a more +# specific reason shown in the parenthesis + +#LOCALIZATION NOTE (netmonitor.headers.blockedByCORSTooltip): This is the tooltip +# displayed on the learnmore link of the blocked by CORS notification. + # LOCALIZATION NOTE (netmonitor.response.name): This is the label displayed -# in the network details response tab identifying an image's file name. +# in the network details response tab identifying an image's file name or font face's name. netmonitor.response.name=Název: # LOCALIZATION NOTE (netmonitor.response.dimensions): This is the label displayed @@ -1005,9 +1054,13 @@ netmonitor.response.dimensions=Rozměry: # LOCALIZATION NOTE (netmonitor.response.mime): This is the label displayed -# in the network details response tab identifying an image's mime. +# in the network details response tab identifying an image's or font's MIME type. netmonitor.response.mime=Typ MIME: +# LOCALIZATION NOTE (netmonitor.response.fontPreviewFailed): This is the notice displayed +# in the network details response tab if the font preview could not be generated due to +# an error. + # LOCALIZATION NOTE (netmonitor.timings.blocked): This is the label displayed # in the network details timings tab identifying the amount of time spent # in a "blocked" state. @@ -1344,10 +1397,28 @@ # above the query string entry in the custom request form netmonitor.custom.query=Řetězec dotazu: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Hlavičky požadavku +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Tělo požadavku: @@ -1360,6 +1431,12 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Zrušit +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Zpět @@ -1446,4 +1523,3 @@ # LOCALIZATION NOTE (netmonitor.errorpanel.fileBugButton): This is the text that appears in the button to visit the bug filing link. # LOCALIZATION NOTE (netmonitor.errorpanel.reloadPanelInfo): This is the text that appears after Network panel errors to instruct the user to reload the panel. - diff -Nru thunderbird-91.7.0+build2/l10n/cs/devtools/client/toolbox.properties thunderbird-91.8.1+build1/l10n/cs/devtools/client/toolbox.properties --- thunderbird-91.7.0+build2/l10n/cs/devtools/client/toolbox.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/devtools/client/toolbox.properties 2022-04-15 07:51:15.000000000 +0000 @@ -26,6 +26,9 @@ # toolbox as a whole toolbox.label=Nástroje pro vývojáře +# LOCALIZATION NOTE (options.autoTheme.label) +# Used as a label for auto theme + # LOCALIZATION NOTE (options.toolNotSupportedMarker): This is the template # used to add a * marker to the label for the Options Panel tool checkbox for the # tool which is not supported for the current toolbox target. @@ -42,6 +45,16 @@ # shortcuts: Cmd+Shift+C or Cmd+Opt+C toolbox.elementPicker.mac.tooltip=Výběr prvku na stránce (%1$S nebo %2$S) +# LOCALIZATION NOTE (toolbox.androidElementPicker.tooltip) +# This is the tooltip of the element picker button in the about:devtools-toolbox toolbox toolbar +# when debugging an Android device +# %S is the keyboard shortcut that toggles the element picker. + +# LOCALIZATION NOTE (toolbox.androidElementPicker.mac.tooltip) +# Like toolbox.androidElementPicker.tooltip, but for macOS as there are two possible keyboard +# shortcuts (Cmd+Shift+C or Cmd+Opt+C) +# %1$S and %2$S are the keyboard shortcuts that toggle the element picker. + # LOCALIZATION NOTE (toolbox.elementPicker.key) # Key shortcut used to toggle the element picker. toolbox.elementPicker.key=CmdOrCtrl+Shift+C @@ -69,6 +82,18 @@ toolbox.resumeOrderWarning=Po spuštění v debuggeru se stránka neobnovila. Pro nápravu prosím nástroje zavřete a znovu otevřete. +# LOCALIZATION NOTE (toolbox.autoThemeNotification) +# Notification displayed in the toolbox notification box when the DevTools theme +# is set to auto and the user is using a dark Firefox theme. +# %S is the brand shorter name (eg Firefox) + +# LOCALIZATION NOTE (toolbox.autoThemeNotification.settingsButton) +# Text of the button displayed in the auto theme notification to open the settings +# panel. +# "Settings" refers to the name of the settings panel, and should most likely be +# the same as toolbox.meatballMenu.settings.label. +toolbox.autoThemeNotification.settingsButton=Otevřít nastavení + # LOCALIZATION NOTE (toolbox.help.key) # Key shortcut used to open the options panel toolbox.help.key=F1 @@ -83,7 +108,7 @@ # LOCALIZATION NOTE (toolbox.zoom*.key) # Key shortcuts used to zomm in/out or reset the toolbox -# Should match fullZoom*Cmd.commandkey values from browser.dtd +# Should match full-zoom-*-shortcut values from browserSets.ftl toolbox.zoomIn.key=CmdOrCtrl+Plus toolbox.zoomIn2.key=CmdOrCtrl+= @@ -275,3 +300,5 @@ # LOCALIZATION NOTE (options.enableMultiProcessToolbox): This is the text that appears in the # settings panel for the checkbox that enables the Multiprocess Browser Toolbox. +# LOCALIZATION NOTE (options.enableNewPerformancePanel): This is the text that appears in the +# settings panel for the checkbox that enables the new performance panel. diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/aboutDialog.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Co je nového diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/aboutImport.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/aboutImport.ftl 2022-04-15 07:51:17.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Zvolte, odkud chcete importovat účty, kontakty, kalendáře a další data: import-address-book = Import souboru s kontakty import-calendar = Import souboru s kalendářem +export-profile = Export ## Buttons button-cancel = Zrušit button-back = Zpět button-continue = Pokračovat +button-export = Exportovat ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Import z aplikace { $app } @@ -26,17 +33,44 @@ profile-file-picker-dir = Vyberte složku profilu profile-file-picker-zip = Vyberte soubor ZIP (menší než 2 GB) items-pane-title = Zvolte, co chcete importovat -items-pane-desc = Importovat z +items-pane-source = Umístění zdroje: items-pane-checkbox-accounts = Účty a nastavení items-pane-checkbox-address-books = Kontakty items-pane-checkbox-calendars = Kalendáře items-pane-checkbox-mail-messages = E-mailové zprávy +## Import from address book file steps + +import-from-addr-book-file-desc = Vyberte typ souboru, který chcete importovat: +addr-book-csv-file = Soubor s hodnotami oddělenými čárkami nebo tabulátory (.csv, .tsv) +addr-book-ldif-file = Soubor LDIF (.ldif) +addr-book-vcard-file = Soubor vCard (.vcf, .vcard) +addr-book-sqlite-file = Soubor databáze SQLite (.sqlite) +addr-book-mab-file = Databáze Mork (.mab) +addr-book-file-picker = Vyberte soubor s kontakty +addr-book-directories-pane-title = Vyberte adresář, kam chcete kontakty importovat: +addr-book-directories-pane-source = Zdrojový soubor: +addr-book-import-into-new-directory = Vytvořit nový adresář + ## Import dialog progress-pane-title = Probíhá import +progress-pane-importing = Probíhá import +progress-pane-exporting = Probíhá export +progress-pane-finished-desc = Dokončeno. progress-pane-restart-desc = Pro dokončení importu restartujte aplikaci. error-pane-title = Chyba error-message-zip-file-too-big = Vybraný soubor ZIP je větší než 2 GB. Nejprve ho prosím rozbalte na disk a poté importujte rozbalený adresář. error-message-extract-zip-file-failed = Soubor ZIP se nepodařilo rozbalit. Rozbalte ho prosím ručně a naimportujte místo něj výslednou složku. error-message-failed = Import se nepodařilo provést. Podrobnosti mohou být dostupné v chybové konzoli. +error-export-failed = Export se nepodařilo provést. Podrobnosti mohou být dostupné v chybové konzoli. + +## element + +csv-source-field = Zdrojové pole +csv-source-first-record = První záznam +csv-source-second-record = Druhý záznam + +## Export tab + +export-profile-desc2 = Pokud je váš aktuální profil větší než 2 GB, doporučujeme ho zazálohovat ručně. diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:51:17.000000000 +0000 @@ -4,21 +4,18 @@ carddav-window = .title = Nová složka kontaktů CardDAV - +carddav-window-title = Nová složka kontaktů CardDAV carddav-dialog = .buttonlabelaccept = Pokračovat .buttonaccesskeyaccept = P - carddav-username-label = .value = Uživatelské jméno: .accesskey = U - carddav-location-label = .value = Adresa: .accesskey = A carddav-location = .default-placeholder = URL adresa nebo adresa serveru s adresářem - carddav-loading = Vyhledávání nastavení… carddav-known-incompatible = Adresa { $url } je známa jako nekompatibilní s { -brand-short-name.gender -> @@ -30,5 +27,4 @@ carddav-connection-error = Chyba spojení. carddav-none-found = U zadaného účtu nebyly nalezeny žádné složky kontaktů, které by bylo možné přidat. carddav-already-added = Všechny složky kontaktů zadaného účtu už jsou přidány. - carddav-available-books = Dostupné složky kontaktů: diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:51:17.000000000 +0000 @@ -143,8 +143,8 @@ about-addressbook-details-home-address-header = Adresy domů about-addressbook-details-work-address-header = Adresy do zaměstnání about-addressbook-details-other-info-header = Další údaje -about-addressbook-prompt-to-save-title = Uložit změny? -about-addressbook-prompt-to-save = Chcete uložit provedené změny? +about-addressbook-unsaved-changes-prompt-title = Neuložené změny +about-addressbook-unsaved-changes-prompt = Chcete před opuštěním režimu úprav uložit provedené změny? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -3,7 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Addressing widget +## Addressing widget # $type (String) - the type of the addressing row remove-address-row-button = @@ -45,7 +45,7 @@ .label = Rozbalit seznam .accesskey = R -# Attachment widget +## Attachment widget ctrl-cmd-shift-pretty-prefix = { PLATFORM() -> @@ -90,6 +90,14 @@ .tooltiptext = Zobrazí lištu příloh ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Skryje lištu příloh ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } příloha + [one] { $count } příloha + [few] { $count } přílohy + *[other] { $count } příloh + } attachment-area-show = .title = Zobrazí lištu příloh ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -102,7 +110,7 @@ } drop-file-label-inline = Vložit do obsahu -# Reorder Attachment Panel +## Reorder Attachment Panel move-attachment-first-panel-button = .label = Přesunout na začátek @@ -116,14 +124,14 @@ .label = Potvrzení o přijetí .tooltiptext = Zažádá o potvrzení o přijetí této zprávy -# Encryption +## Encryption message-to-be-signed-icon = .alt = Podepsat zprávu message-to-be-encrypted-icon = .alt = Zašifrovat zprávu -# Addressing Area +## Addressing Area to-compose-address-row-label = .value = Komu @@ -248,3 +256,63 @@ compose-tool-button-remove-text-styling = .tooltiptext = Odebrat formátování textu + +## FileLink + + +# Template + +# A line of text describing how many uploaded files have been appended to this +# message. Emphasis should be on sharing as opposed to attaching. This item is +# used as a header to a list, hence the colon. +cloud-file-count-header = + { $count -> + [one] Připojil jsem k tomuto e-mailu { $count } soubor: + [few] Připojil jsem k tomuto e-mailu { $count } soubory: + *[other] Připojil jsem k tomuto e-mailu { $count } souborů: + } +# A text used in a footer, instructing the reader where to find additional +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Zjistit více o službě { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Další informace o službách { $firstLinks } a { $lastLink }. +# Tooltip for an icon, indicating that the link is protected by a password. +cloud-file-tooltip-password-protected-link = Odkaz chráněný heslem +# Used in a list of stats about a specific file +# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Size - the size of the file (Size: 4.2 MB) +# Link - the link to the file (Link: https://some.provider.com) +# Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) +# Download Limit - stating the maximum allowed downloads, before the link becomes invalid +# (Download Limit: 6) +cloud-file-template-service = Služba CloudFile: +cloud-file-template-size = Velikost: +cloud-file-template-link = Odkaz: +cloud-file-template-password-protected-link = Odkaz chráněný heslem: +cloud-file-template-expiry-date = Datum vypršení platnosti: +cloud-file-template-download-limit = Omezení počtu stažení: + +# Messages + +# $provider (string) - name of the online storage service that reported the error +cloud-file-connection-error-title = Chyba spojení +cloud-file-connection-error = { -brand-short-name } je offline, ke službě { $provider } se nelze připojit. +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was uploaded and caused the error +cloud-file-upload-error-with-custom-message-title = Nahrávání souboru { $filename } do služby { $provider } se nezdařilo +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-rename-error-title = Chyba přejmenování +cloud-file-rename-error = Vyskytl se problém s přejmenováním souboru { $filename } ve službě { $provider }. +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-rename-error-with-custom-message-title = Přejmenování souboru { $filename } se ve službě { $provider } nezdařilo +# $provider (string) - name of the online storage service that reported the error +cloud-file-rename-not-supported = { $provider } nepodporuje přejmenování již nahraných souborů. diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/messenger.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/messenger.ftl 2022-04-15 07:51:17.000000000 +0000 @@ -183,3 +183,47 @@ [few] { $failures } z { $total } zpráv se nepodařilo dešifrovat a nemohly být zkopírovány. *[other] { $failures } z { $total } zpráv se nepodařilo dešifrovat a nemohlo být zkopírováno. } + +## Spaces toolbar + +spaces-toolbar-button-mail = + .title = Přepnout na panel s poštou +spaces-toolbar-button-address-book = + .title = Přepnout na panel s kontakty +spaces-toolbar-button-calendar = + .title = Přepnout na panel s kalendářem +spaces-toolbar-button-tasks = + .title = Přepnout na panel s úkoly +spaces-toolbar-button-chat = + .title = Přepnout na panel s chatem +spaces-toolbar-button-settings = + .title = Přepnout na panel s nastavením +spaces-context-new-tab-item = + .label = Otevřít v novém panelu +spaces-context-new-window-item = + .label = Otevřít v novém okně +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Přepnout na panel { $tabName } +settings-context-open-settings-item = + .label = Otevřít nastavení +settings-context-open-account-settings-item = + .label = Otevřít nastavení účtu +settings-context-open-addons-item = + .label = Otevřít správce doplňků + +## Spaces toolbar pinned tab menupopup + +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/migration.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/migration.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/migration.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/migration.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -0,0 +1,21 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +migration-progress-header = + { -brand-short-name.gender -> + [masculine] Příprava { -brand-short-name(case: "gen") }… + [feminine] Příprava { -brand-short-name(case: "gen") }… + [neuter] Příprava { -brand-short-name(case: "gen") }… + *[other] Příprava aplikace { -brand-short-name }… + } + +## Migration tasks + + +# These strings are displayed to the user if a migration is taking a long time. +# They should be short (no more than a handful of words) and in the present tense. + +migration-task-test-fast = Testování rychlé změny +migration-task-test-slow = Testování pomalé změny +migration-task-test-progress = Testování ukazatele průběhu diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/otr/add-finger.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/otr/add-finger.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Přidat otisk klíče OTR - +otr-add-finger-title = Přidat otisk klíče OTR # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Zadejte otisk klíče OTR pro { $name }. - otr-add-finger-fingerprint = Otisk: otr-add-finger-tooltip-error = Byl zadán neplatný znak. Povolena jsou pouze písmena ABCDEF a čísla. - otr-add-finger-input = .placeholder = Otisk klíče OTR dlouhý 40 znaků diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/otr/finger.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/otr/finger.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Zavřít .title = Známé otisky klíčů OTR - +otr-finger-title = Dříve viděné otisky klíčů OTR finger-intro = Otisky klíčů OTR z předchozích šifrovaných konverzací. - finger-screen-name = .label = Kontakt finger-verified = .label = Stav ověření finger-fingerprint = .label = Otisk - finger-remove = .label = Odebrat vybrané - finger-remove-all = .label = Odebrat vše diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/otr/otrUI.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/otr/otrUI.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -6,86 +6,60 @@ refresh-label = Obnovit šifrovanou konverzaci auth-label = Ověřit identitu kontaktu reauth-label = Znovu ověřit identitu kontaktu - auth-cancel = Zrušit auth-cancel-access-key = Z - auth-error = Při ověřování identity kontaktu došlo k chybě. auth-success = Identita kontaktu byla úspěšně ověřena. auth-success-them = Kontakt úspěšně ověřil vaši identitu. Možná budete chtít ověřit zase jeho identitu položením své otázky. auth-fail = Ověření identity kontaktu se nezdařilo. auth-waiting = Čekání na dokončení ověření kontaktem… - finger-verify = Ověřit finger-verify-access-key = O - +finger-ignore = Ignorovat +finger-ignore-access-key = I # Do not translate 'OTR' (name of an encryption protocol) buddycontextmenu-label = Přidat otisk klíče OTR - # Variables: # $name (String) - the screen name of a chat contact person alert-start = Probíhá pokus o zahájení šifrované konverzace s uživatelem { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-refresh = Probíhá pokus o obnovení šifrované konverzace s uživatelem { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-gone-insecure = Šifrovaná konverzace s uživatelem { $name } skončila. - # Variables: # $name (String) - the screen name of a chat contact person finger-unseen = Identita uživatele { $name } ještě nebyla ověřena. Příležitostné odposlouchávání možné není, ale s vynaložením určitého úsilí odposlech možný je. Předejděte tomu ověřením identity tohoto kontaktu. - # Variables: # $name (String) - the screen name of a chat contact person finger-seen = Uživatel { $name } vás kontaktuje z neznámého počítače. Příležitostné odposlouchávání možné není, ale s vynaložením určitého úsilí odposlech možný je. Předejděte tomu ověřením identity tohoto kontaktu. - state-not-private = Aktuální konverzace není soukromá. - state-generic-not-private = Aktuální konverzace není soukromá. - # Variables: # $name (String) - the screen name of a chat contact person state-unverified = Aktuální konverzace je šifrovaná, ale není soukromá, protože identita uživatele { $name } ještě nebyla ověřena. - state-generic-unverified = Aktuální konverzace je šifrovaná, ale není soukromá, protože některé identity ještě nebyly ověřeny. - # Variables: # $name (String) - the screen name of a chat contact person state-private = Identita uživatele { $name } byla ověřena. Aktuální konverzace je šifrovaná a soukromá. - state-generic-private = Aktuální konverzace je šifrovaná a soukromá. - # Variables: # $name (String) - the screen name of a chat contact person state-finished = Uživatel { $name } s vámi ukončil šifrovanou konverzaci, měli byste udělat totéž. - state-not-private-label = Nezabezpečeno state-unverified-label = Neověřeno state-private-label = Soukromé state-finished-label = Ukončeno - # Variables: # $name (String) - the screen name of a chat contact person verify-request = Uživatel { $name } požádal o ověření vaší identity. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-private = Ověřili jste identitu uživatele { $name }. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-unverified = Identita uživatele { $name } nebyla ověřena. - -verify-title = Ověřit identitu kontaktu -error-title = Chyba -success-title = Koncové šifrování -success-them-title = Ověřit identitu kontaktu -fail-title = Nelze ověřit -waiting-title = Žádost o ověření byla odeslána - # Do not translate 'OTR' (name of an encryption protocol) # Variables: # $error (String) - contains an error message that describes the cause of the failure diff -Nru thunderbird-91.7.0+build2/l10n/cs/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/cs/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/cs/mail/messenger/preferences/preferences.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/mail/messenger/preferences/preferences.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -163,15 +163,16 @@ .label = Obnovit výchozí .accesskey = O default-search-engine = Výchozí vyhledávač -add-search-engine = - .label = Přidat ze souboru - .accesskey = s add-web-search-engine = .label = Přidat… .accesskey = a remove-search-engine = .label = Odebrat .accesskey = r +add-opensearch-provider-title = Přidat poskytovatele OpenSearch +add-opensearch-provider-text = Zadejte URL adresu poskytovatele OpenSearch, kterého chcete přidat. Použijte buď přímou adresu popisného souboru OpenSearch, nebo adresu, kde ho lze automaticky zjistit. +adding-opensearch-provider-failed-title = Přidání poskytovatele OpenSearch se nezdařilo +adding-opensearch-provider-failed-text = Poskytovatele OpenSearch pro { $url } nelze přidat. minimize-to-tray-label = .label = Při minimalizaci { -brand-short-name.gender -> @@ -245,6 +246,9 @@ smooth-scrolling-label = .label = Použít plynulé posouvání .accesskey = l +browsing-gtk-use-non-overlay-scrollbars = + .label = Vždy zobrazovat posuvníky + .accesskey = o system-integration-legend = Nastavení systému always-check-default = .label = @@ -404,12 +408,6 @@ .accesskey = a search-handler-table = .placeholder = Filtrovat typy obsahu a akcí -type-column-label = - .label = Typ obsahu - .accesskey = T -action-column-label = - .label = Akce - .accesskey = A type-column-header = Typ obsahu action-column-header = Akce save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/cs/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/cs/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/cs/netwerk/necko.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/netwerk/necko.properties 2022-04-15 07:51:15.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Cookie „%1$S“ byla odmítnuta, protože vypršela její doba platnosti. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Cookie „%1$S“ byla odmítnuta, protože je poslána v kontextu cross-site, ale obsahuje příznak „SameSite“ s hodnotou „Lax“ nebo „Strict“. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Varování: „%1$S“ je zastaralé, použijte prosím „%2$S“ diff -Nru thunderbird-91.7.0+build2/l10n/cs/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/cs/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/cs/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:51:15.000000000 +0000 @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Zobrazení ve světlých barvách aboutReader.toolbar.colorschemedark = Zobrazení v tmavých barvách aboutReader.toolbar.colorschemesepia = Zobrazení v sépiových barvách +aboutReader.toolbar.colorschemeauto = Automatický barevný vzhled diff -Nru thunderbird-91.7.0+build2/l10n/cs/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/cs/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/cs/toolkit/chrome/global/narrate.properties 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/toolkit/chrome/global/narrate.properties 2022-04-15 07:51:15.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Poslechnout back = Zpět start = Spustit stop = Zastavit +# %S is the keyboard shortcut for the start command +start-label = Spustit (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Zastavit (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Vpřed speed = Rychlost selectvoicelabel = Hlas: diff -Nru thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/about/aboutThirdParty.ftl thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/about/aboutThirdParty.ftl --- thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/about/aboutThirdParty.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/about/aboutThirdParty.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -10,18 +10,15 @@ [neuter] { -brand-short-name(case: "loc") } *[other] aplikaci { -brand-short-name } } - third-party-intro = - Tato stránka zobrazuje seznam modulů třetích stran, které byly vloženy do { -brand-short-name.gender -> - [masculine] vašeho { -brand-short-name(case: "gen") } - [feminine] vaší { -brand-short-name(case: "gen") } - [neuter] vašeho { -brand-short-name(case: "gen") } - *[other] vaší aplikace { -brand-short-name } - }. Za modul třetí strany je považovaný každý modul, který není podepsaný Microsoftem nebo { -vendor-short-name(case: "ins") }. - + { -brand-short-name.gender -> + [masculine] Tato stránka zobrazuje seznam modulů třetích stran, které byly vneseny do vašeho { -brand-short-name(case: "gen") }. Za modul třetí strany je považovaný každý modul, který není podepsaný Microsoftem nebo { -vendor-short-name(case: "ins") }. + [feminine] Tato stránka zobrazuje seznam modulů třetích stran, které byly vneseny do vaší { -brand-short-name(case: "gen") }. Za modul třetí strany je považovaný každý modul, který není podepsaný Microsoftem nebo { -vendor-short-name(case: "ins") }. + [neuter] Tato stránka zobrazuje seznam modulů třetích stran, které byly vneseny do vašeho { -brand-short-name(case: "gen") }. Za modul třetí strany je považovaný každý modul, který není podepsaný Microsoftem nebo { -vendor-short-name(case: "ins") }. + *[other] Tato stránka zobrazuje seznam modulů třetích stran, které byly vneseny do vaší aplikace { -brand-short-name }. Za modul třetí strany je považovaný každý modul, který není podepsaný Microsoftem nebo { -vendor-short-name(case: "ins") }. + } third-party-message-empty = Nebyly nalezeny žádné moduly třetích stran. third-party-message-no-duration = Nezaznamenáno - third-party-detail-version = Verze souboru third-party-detail-vendor = Informace poskytovatele third-party-detail-occurrences = Výskyty @@ -30,11 +27,9 @@ .title = Jak dlouho tento modul aplikaci blokoval. third-party-detail-app = Aplikace third-party-detail-publisher = Autor - third-party-th-process = Proces third-party-th-duration = Doba načítání (ms) third-party-th-status = Stav - third-party-tag-ime = IME .title = Tento typ modulu, je načten když používáte IME třetí strany. third-party-tag-shellex = Rozšíření shellu @@ -51,11 +46,9 @@ [neuter] { -brand-short-name } spadlo *[other] Aplikace { -brand-short-name } spadla } při vykonávání kódu tohoto modulu - third-party-status-loaded = Načtený third-party-status-blocked = Zablokovaný third-party-status-redirected = Přesměrovaný - third-party-button-copy-to-clipboard = Zkopírovat data do schránky third-party-button-reload = Znovu načíst se systémovými informacemi .title = Znovu načíst se systémovými informacemi diff -Nru thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -18,6 +18,8 @@ about-webrtc-aec-logging-off-state-label = Spustit protokol AEC about-webrtc-aec-logging-on-state-label = Zastavit protokol AEC about-webrtc-aec-logging-on-state-msg = Protokol AEC je aktivní (hovořte s volajícím pár minut, a pak zastavte sběr) +# The autorefresh checkbox causes the page to autorefresh its content when checked +about-webrtc-auto-refresh-label = Automatické opětovné načtení ## @@ -183,6 +185,24 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } snímek + [few] { $frames } snímky + *[other] { $frames } snímků + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } kanál + [few] { $channels } kanály + *[other] { $channels } kanálů + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -9,11 +9,6 @@ experimental-features-css-masonry-description = Zapne podporu experimentálního CSS Masonry Layoutu. Podrobnosti o této funkci najdete zde. Zpětnou vazbu nám můžete napsat zde na GitHubu nebo do tohoto bugu. # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. -experimental-features-css-cascade-layers = - .label = CSS: Cascade Layers -experimental-features-css-cascade-layers-description = Zapne podporu vrstev CSS Cascade Layers. Podrobnosti najdete v rozpracované specifikaci a bugu 1699215. -# The title of the experiment should be kept in English as it may be referenced -# by various online articles and is technical in nature. experimental-features-web-gpu2 = .label = Web API: WebGPU experimental-features-web-gpu-description2 = Toto nové API poskytuje nízkoúrovňový přístup k provádění výpočtů a vykreslování grafiky pomocí grafického procesoru (GPU) uživatelského zařízení. Jeho specifikace je stále rozpracovaná. Podrobnosti najdete v bugu 1602129. @@ -117,3 +112,7 @@ experimental-features-ime-search = .label = Adresní řádek: zobrazovat výsledky při použití IME experimental-features-ime-search-description = IME (Input Method Editor) je nástroj pro zadávání komplexních symbolů, jako jsou znaky východoasijských nebo indických jazyků, pomocí běžné klávesnice. Po zapnutí tohoto experimentu bude panel adresního řádku zobrazovat výsledky vyhledávání a návrhy našeptávače i při použití IME pro zadávání textu. Protože IME může zakrýt výsledky adresního řádku, doporučujeme tuto předvolbu použít jen s IME, který toto nedělá. +# Firefox 100 +experimental-features-firefox-100 = + .label = Řetězec User-Agent pro { -brand-product-name } 100 +experimental-features-firefox-100-description = { -brand-short-name } bude posílat webovým stránkám řetězec User-Agent odpovídající jeho verzi 100. Tuto volbu můžete použít pro otestování stránek, zda fungují i s třícifernou verzí { -brand-short-name(case: "gen") }. Finální vydání { -brand-product-name(case: "gen") } 100 je naplánováno na květen 2022. diff -Nru thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/cs/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:36:31.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cs/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:51:15.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socket # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Sandboxovaný IPC Actor ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/cy/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/cy/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/cy/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:51:22.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Preifatrwydd: Digwyddiad Preifat calendar-editable-item-privacy-icon-confidential = .alt = Preifatrwydd: Dangos Amser a Dyddiad yn Unig +calendar-editable-item-recurrence = + .alt = Yn ailadrodd +calendar-editable-item-recurrence-exception = + .alt = Eithriad ailadrodd calendar-editable-item-todo-icon-task = .alt = Tasg calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/cy/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/cy/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/cy/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = Mae { $organizer } wedi eich gwahodd i: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Cadw +calendar-invitation-panel-accept-button = Iawn +calendar-invitation-panel-decline-button = Na +calendar-invitation-panel-tentative-button = Efallai +calendar-invitation-panel-reply-status = * Nid ydych wedi penderfynu nac ymateb eto +calendar-invitation-panel-prop-title-when = Pryd: +calendar-invitation-panel-prop-title-location = Lleoliad: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Mynychwyr: +calendar-invitation-panel-prop-title-description = Disgrifiad: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } iawn + [DECLINED] { $count } na + [TENTATIVE] { $count } efallai + [NEEDS-ACTION] { $count } yn disgwyl ateb + [TOTAL] { $count } mynychwyr + *[OTHER] { $count } arall + } diff -Nru thunderbird-91.7.0+build2/l10n/cy/chat/matrix.properties thunderbird-91.8.1+build1/l10n/cy/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/cy/chat/matrix.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/chat/matrix.properties 2022-04-15 07:51:22.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=Diddymodd %1$S y gwiriad oherwydd: %2$S message.verification.done=Gwirio wedi'i gwblhau. +message.decryptionError=Wedi methu â dadgryptio cynnwys y neges hon. I ofyn am allweddi amgryptio o'ch dyfeisiau eraill, de-gliciwch y neges hon. +message.decrypting=Wrthi'n dadgryptio... +message.redacted=Neges wedi'i guddolygu. + +# Label in the message context menu +message.action.requestKey=Gofyn eto am Allweddi +message.action.redact=Cuddolygu +message.action.report=Adrodd am Neges +message.action.retry=Ceisiwch Anfon Eto +message.action.cancel=Diddymu Neges + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Digwyddodd gwall wrth anfon eich neges "%1$S". diff -Nru thunderbird-91.7.0+build2/l10n/cy/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/cy/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/cy/devtools/client/aboutdebugging.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/devtools/client/aboutdebugging.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Dadfygio - Gosod - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Dadfygio - Amser Rhedeg/ { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Y { -brand-shorter-name } hwn - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Gosod - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB wedi'i alluogi - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB wedi ei analluogi - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Cysylltwyd # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Datgysylltwyd - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = Heb ddarganfod unrhyw ddyfeisiau - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Cysylltu - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Cysylltu… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Methodd y cysylltiad - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = Cysylltiad yn yr arfaeth o hyd, gwiriwch am negeseuon ar y porwr targed - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = Cysylltiad wedi dod i ben - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Aros am borwr... - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Wedi'i ddatgysylltu - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Cefnogaeth dadfygio - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Eicon Cymorth - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Adnewyddu dyfeisiau @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Gosod - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Ffurfweddwch y dull cysylltu rydych chi eisiau dadfygio eich dyfais o bell gydag ef. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Defnyddiwch { about-debugging-this-firefox-runtime-name } i ddadfygio tabiau, estyniadau a gweithwyr gwasanaeth ar y fersiwn hon o { -brand-shorter-name }. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Cysylltu Dyfais - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Bydd galluogi hyn yn llwytho i lawr ac yn ychwanegu'r cydrannau dadfygio Android USB at { -brand-shorter-name }. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = Galluogi Dyfeisiau USB - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = Analluogi Dyfeisiau USB - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Diweddaru… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Galluogwyd about-debugging-setup-usb-status-disabled = Analluogwyd about-debugging-setup-usb-status-updating = Diweddaru… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Galluogi dewislen datblygwyr ar eich dyfais Android. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Galluogi Dadfygio USB yn Newislen Datblygwr Android. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Galluogi Dadfygio USB yn Firefox ar y ddyfais Android. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Cysylltu'r ddyfais Android i'ch cyfrifiadur. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Anhawster cysylltu â'r ddyfais USB? Datrys problemau - # Network section of the Setup page about-debugging-setup-network = .title = Lleoliad Rhwydwaith - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Anawsterau cysylltu drwy leoliad rhwydwaith? Datrys problemau - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Ychwanegu - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = Nid oes unrhyw leoliadau rhwydwaith wedi'u hychwanegu eto. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Gwesteiwr - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Tynnu - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Gwestai annilys “{ $host-value }”.Y fformat disgwyliedig yw “hostname:portnumber”. - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Prosesau - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Perfformiad proffil - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Nid yw ffurfweddiad eich porwr yn cydweddu â Service Workers. Dysgu rhagor - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = Mae gan y porwr cysylltiedig hen fersiwn ({ $runtimeVersion }). Y fersiwn lleiaf sy'n cael ei gynnal yw ({ $minVersion }). Mae hwn yn osodiad sydd dim yn cael ei gynnal a gall achosi i DevTools fethu. Diweddarwch y porwr cysylltiedig. Datrys problemau - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = Nid oes modd i'r fersiwn yma o Firefox ddadfygio Firefox ar gyfer Android (68). Rydym yn argymell gosod Firefox ar gyfer Android Nightly ar eich ffôn i'w brofi. Rhagor o fanylion - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = Mae'r porwr cysylltiedig yn fwy diweddar ( { $runtimeVersion }, buildID { $runtimeID }) na'ch { -brand-shorter-name } ({ $localVersion }, BuildID{ $localID }). Mae hwn yn osodiad heb gefnogaeth ac fe all beri i DevTools fethu. Diweddarwch Firefox. Datrys Problemau - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Datgysylltu - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Galluogi anogyn cysylltu - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Analluogi anogyn cysylltu - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Proffiliwr - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Dim byd eto. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Archwilio - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Llwytho Ychwanegyn Dros Dro… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = Digwyddodd gwall wrth osod ychwanegyn dros dro - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Ail-lwytho - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Tynnu - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Terfynu sgript cefndir # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Dewis ffeil maniffest.json neu .xpi /.zip - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Mae gan y WebExtension ID dros dro. Dysgu rhagor - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = URL Maniffest - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = UUID mewnol - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Lleoliad - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = Enw'r Estyniadau - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Sgript gefndir +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Yn rhedeg +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Ataliawyd # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Gwthio .disabledTitle = Mae Gweithiwr Gwasanaeth gwthio wedi ei analluogi ar hyn o bryd ar gyfer amlbroses { -brand-shorter-name } - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Cychwyn .disabledTitle = Mae Gweithiwr Gwasanaeth gwthio wedi ei analluogi ar hyn o bryd ar gyfer amlbroses { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Dadgofrestru - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Estyn .value = Gwrando am ddigwyddiadau estyn - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Estyn .value = Ddim yn gwrando ar ddigwyddiadau estyn - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Rhedeg - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Wedi Atal - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Cofrestru - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Cwmpas - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Gwasanaeth Gwthio - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = Mae Gweithiwr Gwasanaeth gwthio wedi ei analluogi ar hyn o bryd ar gyfer amlbroses { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Nid yw'r tab wedi'i lwytho'n llawn ac nid oes modd ei archwilio - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Prif Broses - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Prif Broses y porwr targed - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Blwch Offer Amlbroses - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Prif Broses a Phrosesau Cynnwys ar gyfer y porwr targed - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Cau neges - # Label text used for the error details of message component. about-debugging-message-details-label-error = Manylion gwall - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Manylion rhybudd - # Label text used for default state of details of message component. about-debugging-message-details-label = Manylion diff -Nru thunderbird-91.7.0+build2/l10n/cy/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/cy/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/cy/devtools/client/compatibility.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/devtools/client/compatibility.ftl 2022-04-15 07:51:22.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (arbrofol) compatibility-issue-prefixneeded = (angen rhagddodiad) compatibility-issue-deprecated-experimental = (anghymeradwy, arbrofol) - compatibility-issue-deprecated-prefixneeded = (anghymeradwy, angen rhagddodiad) compatibility-issue-experimental-prefixneeded = (arbrofol, angen rhagddodiad) compatibility-issue-deprecated-experimental-prefixneeded = anghymeradwy, arbrofol, angen rhagddodiad) @@ -47,7 +46,14 @@ [many] { $number } digwyddiad *[other] { $number } digwyddiad } - compatibility-no-issues-found = Dim materion cydnawsedd. wedi'u canfod. compatibility-close-settings-button = .title = Cau'r gosodiadau +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Materion cydnawsedd yn: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/cy/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/cy/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/cy/devtools/client/debugger.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/devtools/client/debugger.properties 2022-04-15 07:51:23.000000000 +0000 @@ -642,6 +642,16 @@ ignoreContextItem.unignore=Peidio anwybyddu ffynhonnell ignoreContextItem.unignore.accesskey=P +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Anwybyddu llinell +ignoreContextItem.ignoreLine.accesskey=A + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Dadanwybyddu llinell +ignoreContextItem.unignoreLine.accesskey=L + # LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated # with the ignore lines context menu item ignoreContextItem.ignoreLines=Anwybyddu llinellau diff -Nru thunderbird-91.7.0+build2/l10n/cy/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/cy/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/cy/devtools/client/netmonitor.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/devtools/client/netmonitor.properties 2022-04-15 07:51:23.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → adalw %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=Tynnwyd y llinyn “%S” o ddechrau'r JSON sydd i'w weld isod + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Llinyn Ymholi: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=Paramedrau URL + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Pennyn Gofyn: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Penynnau + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=enw + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=gwerth + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Corff + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=llwyth + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Corff sy'n Gofyn: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Diddymu +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Clirio + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Tynnu eitem + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Nôl diff -Nru thunderbird-91.7.0+build2/l10n/cy/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/cy/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/cy/devtools/client/toolbox.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/devtools/client/toolbox.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Analluogi awtoguddio llamlenni +toolbox-meatball-menu-pseudo-locale-accented = Galluogi locale “acennog”. +toolbox-meatball-menu-pseudo-locale-bidi = Galluogi locale “bidi”. ## diff -Nru thunderbird-91.7.0+build2/l10n/cy/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/cy/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/cy/devtools/client/toolbox-options.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/devtools/client/toolbox-options.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Galluogi dadfygio pell options-enable-remote-tooltip2 = .title = Bydd troi'r dewis hwn ymlaen yn caniatáu dadfygio enghraifft y porwr hwn o bell +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Galluogi fformatwyr cyfaddas +options-enable-custom-formatters-tooltip = + .title = Bydd troi'r dewis hwn ymlaen yn caniatáu i wefannau ddiffinio fformatwyr personol ar gyfer gwrthrychau DOM # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Galluogi Service Workers dros HTTP (pan fydd y blwch offer ar agor) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/cy/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/cy/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/cy/devtools/client/webconsole.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/devtools/client/webconsole.properties 2022-04-15 07:51:23.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=Ffeil +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Copïo pob Neges +webconsole.menu.copyAllMessages.accesskey=N + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Cadw pob Neges i Ffeil +webconsole.menu.saveAllMessagesFile.accesskey=F + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/cy/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/cy/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/cy/dom/chrome/dom/dom.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/dom/chrome/dom/dom.properties 2022-04-15 07:51:23.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Rhowch URL. FormValidationInvalidDate=Rhowch ddyddiad dilys. FormValidationInvalidTime=Rhowch amser dilys. +FormValidationInvalidDateTime=Rhowch ddyddiad ac amser dilys. +FormValidationInvalidDateMonth=Rhowch fis dilys. +FormValidationInvalidDateWeek=Rhowch wythnos ddilys. FormValidationPatternMismatch=Cydweddwch y fformat. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Cydweddwch y fformat: %S. diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/chrome/messenger/aboutDialog.dtd thunderbird-91.8.1+build1/l10n/cy/mail/chrome/messenger/aboutDialog.dtd --- thunderbird-91.7.0+build2/l10n/cy/mail/chrome/messenger/aboutDialog.dtd 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/chrome/messenger/aboutDialog.dtd 2022-04-15 07:51:23.000000000 +0000 @@ -38,7 +38,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/cy/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/cy/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:51:23.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/aboutDialog.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Be sy'n Newydd diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/aboutImport.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/aboutImport.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Dewis i fewnforio Cyfrifon, Llyfrau Cyfeiriadau, Calendrau a data o: import-address-book = Mewnforio Ffeil Llyfr Cyfeiriadau import-calendar = Mewnforio Ffeil Calendr +export-profile = Allforio ## Buttons button-cancel = Diddymu button-back = Nôl button-continue = Parhau +button-export = Allforio ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Mewnforio o { $app } @@ -26,17 +33,52 @@ profile-file-picker-dir = Dewiswch ffolder proffil profile-file-picker-zip = Dewiswch ffeil zip (llai na 2GB) items-pane-title = Dewiswch beth i'w fewnforio -items-pane-desc = Mewnforio o +items-pane-source = Lleoliad y ffynhonnell: items-pane-checkbox-accounts = Cyfrifon a Gosodiadau items-pane-checkbox-address-books = Llyfrau Cyfeiriadau items-pane-checkbox-calendars = Calendrau items-pane-checkbox-mail-messages = Negeseuon E-bost +## Import from address book file steps + +import-from-addr-book-file-desc = Dewiswch y math o ffeil yr hoffech ei mewnforio: +addr-book-csv-file = Ffeil wedi'i gwahanu gan goma neu dab (.csv, .tsv) +addr-book-ldif-file = Ffeil LDIF (.ldif) +addr-book-vcard-file = Ffeil vCard (.vcf, .vcard) +addr-book-sqlite-file = Ffeil cronfa ddata SQLite (.sqlite) +addr-book-mab-file = Ffeil cronfa ddata Mork (.mab) +addr-book-file-picker = Dewiswch ffeil llyfr cyfeiriadau +addr-book-csv-field-map-title = Cydweddu enwau meysydd +addr-book-csv-field-map-desc = Dewiswch feysydd llyfr cyfeiriadau sy'n cyfateb i'r meysydd ffynhonnell. Dad-diciwch y meysydd nad ydych am eu mewnforio. +addr-book-directories-pane-title = Dewiswch y cyfeiriadur yr hoffech ei fewnforio iddo: +addr-book-directories-pane-source = Ffeil ffynhonnell: +addr-book-import-into-new-directory = Crëwch gyfeiriadur newydd + ## Import dialog progress-pane-title = Yn mewnforio +progress-pane-importing = Mewnforio +progress-pane-exporting = Yn allforio +progress-pane-finished-desc = Wedi gorffen. progress-pane-restart-desc = Ailgychwyn i orffen mewnforio. error-pane-title = Gwall error-message-zip-file-too-big = Mae'r ffeil zip a ddewiswyd yn fwy na 2GB. Echdynnwch hi'n gyntaf, yna ei mewnforio o'r ffolder cafodd ei hechdynnu. error-message-extract-zip-file-failed = Wedi methu echdynnu'r ffeil zip. Echdynwch hi â llaw, yna ei mewnforio o'r ffolder wedi'i hechdynnu yn lle hynny. error-message-failed = Methodd y mewnforio yn annisgwyl, efallai y bydd mwy o wybodaeth ar gael yn y Consol Gwallau. +error-export-failed = Methodd y mewnforio yn annisgwyl, efallai y bydd rhagor o wybodaeth ar gael yn y Consol Gwallau. + +## element + +csv-first-row-contains-headers = Mae'r rhes gyntaf yn cynnwys enwau meysydd +csv-source-field = Maes ffynhonnell +csv-source-first-record = Cofnod cyntaf +csv-source-second-record = Ail gofnod +csv-target-field = Maes llyfr cyfeiriadau + +## Export tab + +export-profile-desc = Allforiwch gyfrifon e-bost, negeseuon e-bost, llyfrau cyfeiriadau, gosodiadau i ffeil zip. Pan fo angen, gallwch fewnforio'r ffeil zip i adfer eich proffil. +export-profile-desc2 = Os yw eich proffil presennol yn fwy na 2GB, rydym yn awgrymu eich bod yn gwneud copi wrth gefn ohono ar eich cyfer chi eich hun. +export-open-profile-folder = Agor ffolder proffil +export-file-picker = Allforio i ffeil zip +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Llyfr Cyfeiriadau CardDAV newydd - +carddav-window-title = Llyfr Cyfeiriadau CardDAV Newydd carddav-dialog = .buttonlabelaccept = Parhau .buttonaccesskeyaccept = P - carddav-username-label = .value = Enw Defnyddiwr: .accesskey = E - carddav-location-label = .value = Lleoliad: .accesskey = L carddav-location = .default-placeholder = URL neu enw gwesteiwr gweinydd y llyfr cyfeiriadau - carddav-loading = Chwilio am y ffurfweddiad… carddav-known-incompatible = Mae'n hysbys bod { $url } yn anghydnaws â { -brand-short-name }. carddav-connection-error = Methu cysylltu. carddav-none-found = Heb ddod o hyd i lyfrau cyfeiriadau i'w hychwanegu ar gyfer y cyfrif penodedig. carddav-already-added = Mae'r holl lyfrau cyfeiriadau ar gyfer y cyfrif penodol eisoes wedi'u hychwanegu. - carddav-available-books = Llyfrau cyfeiriadau sydd ar gael: diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -156,8 +156,8 @@ about-addressbook-details-home-address-header = Cyfeiriad Cartref about-addressbook-details-work-address-header = Cyfeiriad Gwaith about-addressbook-details-other-info-header = Manylion Eraill -about-addressbook-prompt-to-save-title = Cadw'r Newidiadau? -about-addressbook-prompt-to-save = Ydych chi eisiau cadw eich newidiadau? +about-addressbook-unsaved-changes-prompt-title = Newidiadau heb eu Cadw +about-addressbook-unsaved-changes-prompt = Ydych chi am gadw'ch newidiadau cyn gadael y wedd golygu? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/menubar.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/menubar.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -67,6 +67,9 @@ mail-uidensity-touch = .label = Cyffwrdd .accesskey = y +menu-spaces-toolbar-button = + .label = Bar Offer Bylchau + .accesskey = B ## File diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -99,6 +99,17 @@ .tooltiptext = Dangos y paen atodi ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Cuddio'r paen atodi ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } Atodiad + [zero] { $count } Atodiadau + [one] { $count } Atodiad + [two] { $count } Atodiad + [few] { $count } Atodiad + [many] { $count } Atodiad + *[other] { $count } Atodiad + } attachment-area-show = .title = Dangos y paen atodi ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -270,8 +281,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Tynnu Steilio Testun -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Wedi'i lwytho i gyfrif Filelink anhysbys. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } - Atodiad Filelink +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = Atodwyd y ffeil { $filename } fel Filelink. Mae modd ei lwytho i lawr o'r ddolen isod. # Template @@ -288,26 +312,27 @@ *[other] Rwyf wedi cysylltu { $count } ffeil i'r e-bost hwn: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [zero] Dysgwch ragor am { $firstLinks } a { $lastLink }. - [one] Dysgwch ragor am { $firstLinks } - [two] Dysgwch ragor am { $firstLinks } a { $lastLink }. - [few] Dysgwch ragor am { $firstLinks } a { $lastLink }. - [many] Dysgwch ragor am { $firstLinks } a { $lastLink }. - *[other] Dysgwch ragor am { $firstLinks } a { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Dysgu rhagor am { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Dysgu rhagor am { $firstLinks } a { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Dolen wedi'i diogelu gan gyfrinair # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = Gwasanaeth CloudFile: +cloud-file-template-service-name = Gwasanaeth Filelink: cloud-file-template-size = Maint: cloud-file-template-link = Dolen: cloud-file-template-password-protected-link = Dolen wedi'i Diogelu gan Gyfrinair @@ -317,6 +342,9 @@ # Messages # $provider (string) - name of the online storage service that reported the error +cloud-file-connection-error-title = Gwall Cysylltiad +cloud-file-connection-error = Mae { -brand-short-name } all-lein. Methu cysylltu â { $provider }. +# $provider (string) - name of the online storage service that reported the error # $filename (string) - name of the file that was uploaded and caused the error cloud-file-upload-error-with-custom-message-title = Methodd Llwytho { $filename } i { $provider } # $provider (string) - name of the online storage service that reported the error @@ -328,3 +356,9 @@ cloud-file-rename-error-with-custom-message-title = Methodd ail-enwi { $filename } ar { $provider } # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = Nid yw { $provider } yn cefnogi ailenwi ffeiliau sydd eisoes wedi'u llwytho i fyny. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Gwall Atodi Filelink +cloud-file-attachment-error = Wedi methu diweddaru'r atodiad Filelink { $filename }, oherwydd bod ei ffeil leol wedi'i symud neu ei dileu. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Gwall Cyfrif Filelink +cloud-file-account-error = Wedi methu diweddaru'r atodiad Filelink { $filename }, oherwydd bod ei ffeil leol wedi'i symud neu ei dileu. diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/messenger.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/messenger.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -177,3 +177,85 @@ ## error messages decrypt-and-copy-failures = Nid oedd modd dadgryptio { $failures } o { $total } o negeseuon ac heb eu copïo. + +## Spaces toolbar + +spaces-toolbar = + .toolbarname = Bar Offer Bylchau +spaces-toolbar-button-mail = + .title = Symud i'r tab e-bost +spaces-toolbar-button-address-book = + .title = Symud i'r tab llyfr cyfeiriadau +spaces-toolbar-button-calendar = + .title = Symud i'r tab calendr +spaces-toolbar-button-tasks = + .title = Symud i'r tab tasgau +spaces-toolbar-button-chat = + .title = Symud i'r tab sgwrsio +spaces-toolbar-button-settings = + .title = Symud i'r tab gosodiadau +spaces-toolbar-button-collapse = + .title = Cau'r bar offer bylchau +spaces-toolbar-button-reveal = + .title = Dangos y bar offer bylchau +spaces-context-new-tab-item = + .label = Agor mewn tab newydd +spaces-context-new-window-item = + .label = Agor mewn ffenestr newydd +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Newid i { $tabName } +settings-context-open-settings-item = + .label = Agor y Gosodiadau +settings-context-open-account-settings-item = + .label = Agor Gosodiadau Cyfrif +settings-context-open-addons-item = + .label = Agor Ychwanegion a Themâu + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Agor dewislen bylchau +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [zero] Dim negeseuon heb eu darllen + [one] Un neges neb ei darllen + [two] { $count } heb eu darllen + [few] { $count } heb eu darllen + [many] { $count } heb eu darllen + *[other] { $count } heb eu darllen + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Cyfaddasu… +spaces-customize-panel-title = Gosodiadau Bylchau Bar Offer +spaces-customize-background-color = Lliw cefndir +spaces-customize-icon-color = Lliw botwm +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Lliw cefndir botwm a ddewiswyd +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Lliw botwm a ddewiswyd +spaces-customize-button-restore = Adfer y Rhagosodiadau + .accesskey = R +spaces-customize-button-save = Gorffen + .accesskey = G diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -16,15 +16,13 @@ .label = Agor manylion a golygu derbyniad... openpgp-one-recipient-status-discover = .label = Darganfod allwedd newydd neu wedi'i diweddaru - openpgp-one-recipient-status-instruction1 = I anfon neges wedi'i hamgryptio o ben-i-ben at dderbynnydd, mae angen i chi gael gafael ar ei allwedd gyhoeddus OpenPGP a'i nodi fel y'i derbyniwyd. openpgp-one-recipient-status-instruction2 = I gael eu allwedd gyhoeddus, eu mewnforio o e-bost y maent wedi'i anfon atoch ac sy'n ei gynnwys. Fel arall, gallwch geisio darganfod eu allwedd gyhoeddus ar gyfeiriadur. - openpgp-key-own = Derbyniwyd (allwedd bersonol) openpgp-key-secret-not-personal = Ddim yn ddefnyddiadwy openpgp-key-verified = Derbyniwyd (dilyswyd) openpgp-key-unverified = Derbyniwyd (heb ei wirio) openpgp-key-undecided = Heb ei dderbyn (heb benderfynu) openpgp-key-rejected = Heb ei dderbyn (gwrthodwyd) - +openpgp-key-expired = Daeth i Ben openpgp-intro = Allweddi cyhoeddus sydd ar gael ar gyfer { $key } diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/otr/add-finger.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/otr/add-finger.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Ychwanegu bysbrint Allwedd OTR - +otr-add-finger-title = Ychwanegu bysbrint Allwedd OTR # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Rhowch bysbrint allwedd OTR ar gyfer { $name }. - otr-add-finger-fingerprint = Bysbrint otr-add-finger-tooltip-error = Nod annilys wedi'i roi. Dim ond llythrennau ABCDEF a rhifau sy'n cael eu caniatáu - otr-add-finger-input = .placeholder = Bysbrint allwedd OTR 40 nod o hyd diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/otr/finger.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/otr/finger.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Cau .title = Bysprintiau OTR Blaenorol - +otr-finger-title = Bysbrintiau OTR a Welwyd Eisoes finger-intro = Bysprintiau allweddol OTR o sgyrsiau amgryptiedig blaenorol o'r pen-i-ben. - finger-screen-name = .label = Cyswllt finger-verified = .label = Statws Gwirio finger-fingerprint = .label = Bysbrint - finger-remove = .label = Tynnu'r Dewis - finger-remove-all = .label = Tynnu'r Cyfan diff -Nru thunderbird-91.7.0+build2/l10n/cy/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/cy/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/cy/mail/messenger/preferences/preferences.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/mail/messenger/preferences/preferences.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -116,9 +116,6 @@ .label = Adfer y Rhagosodiad .accesskey = R default-search-engine = Peiriant Chwilio Rhagosodedig -add-search-engine = - .label = Ychwanegu o ffeil - .accesskey = Y add-web-search-engine = .label = Ychwanegu… .accesskey = Y @@ -196,6 +193,9 @@ smooth-scrolling-label = .label = Defnyddio sgrolio llyfn .accesskey = l +browsing-gtk-use-non-overlay-scrollbars = + .label = Dango bariau sgrolio bob tro + .accesskey = D system-integration-legend = Integreiddio System always-check-default = .label = Gwirio bob tro os { -brand-short-name } yw'r rhaglen e-bost rhagosodedig wrth gychwyn @@ -320,12 +320,6 @@ .accesskey = L search-handler-table = .placeholder = Hidlo mathau a gweithredoedd cynnwys -type-column-label = - .label = Math o Gynnwys - .accesskey = M -action-column-label = - .label = Gweithred - .accesskey = G type-column-header = Math o Gynnwys action-column-header = Gweithred save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/cy/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/cy/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/cy/netwerk/necko.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/netwerk/necko.properties 2022-04-15 07:51:23.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Mae cwci “%1$S” wedi’i wrthod am ei fod eisoes wedi dod i ben. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Gwrthodwyd cwci “%1$S” oherwydd ei fod mewn cyd-destun traws-safle a’i “SameSite” yw “Lax” neu “Strict”. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Rhybudd: mae ‘%1$S’ yn anghymeradwy, defnyddiwch ‘%2$S’ diff -Nru thunderbird-91.7.0+build2/l10n/cy/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/cy/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/cy/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:51:23.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Cau'r Golwg Darllen @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Cynllun Lliw Golau aboutReader.toolbar.colorschemedark = Cynllun Lliw Tywyll aboutReader.toolbar.colorschemesepia = Cynllun Lliw Sepia +aboutReader.toolbar.colorschemeauto = Cynllun Lliw Awtomatig diff -Nru thunderbird-91.7.0+build2/l10n/cy/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/cy/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/cy/toolkit/chrome/global/narrate.properties 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/toolkit/chrome/global/narrate.properties 2022-04-15 07:51:23.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Gwrando back = Nôl start = Cychwyn stop = Atal +# %S is the keyboard shortcut for the start command +start-label = Cychwyn (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Atal (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Ymlaen speed = Cyflymder selectvoicelabel = Llais: diff -Nru thunderbird-91.7.0+build2/l10n/cy/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/cy/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/cy/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -185,6 +185,30 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [zero] { $frames } fframiau + [one] { $frames } ffrâm + [two] { $frames } ffrâm + [few] { $frames } ffrâm + [many] { $frames } ffrâm + *[other] { $frames } ffrâm + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [zero] { $channels } sianeli + [one] { $channels } sianel + [two] { $channels } sianel + [few] { $channels } sianel + [many] { $channels } sianel + *[other] { $channels } sianel + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/cy/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/cy/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/cy/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Bar Cyfeiriadau: dangos canlyniadau wrth ddefnyddio'r IME experimental-features-ime-search-description = Offeryn yw IME (Golygydd Dull Mewnbwn) sy'n eich galluogi i nodi symbolau cymhleth, fel y rhai sy'n cael eu ddefnyddio mewn ieithoedd ysgrifenedig yn Nwyrain Asia neu India, gan ddefnyddio bysellfwrdd safonol. Bydd galluogi'r arbrawf hwn yn cadw'r panel bar cyfeiriadau ar agor, dangos canlyniadau chwilio ac awgrymiadau, tra'n defnyddio IME i fewnbynnu testun. Sylwch y gallai'r IME ddangos panel sy'n ymdrin â chanlyniadau'r bar cyfeiriad, felly mae'r dewis hwn yn cael ei awgrymu ar gyfer IME sydd ddim yn defnyddio'r math hwn o banel. +# Firefox 100 +experimental-features-firefox-100 = + .label = 100 Llinyn Defnyddiwr-Asiant { -brand-product-name } +experimental-features-firefox-100-description = Gwnewch i { -brand-short-name } anfon llinyn Defnyddiwr-Asiant i wefannau sy'n esgus bod yn { -brand-product-name } fersiwn 100. Defnyddiwch y gosodiad hwn i brofi a fydd gwefannau'n torri pan fydd { -brand-short-name } yn taro rhif fersiwn tri digid. Mae'r gwir { -brand-product-name } 100 i fod i gael ei ryddhau ym mis Mai 2022, felly dechreuwch brofi'ch gwefannau nawr! diff -Nru thunderbird-91.7.0+build2/l10n/cy/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/cy/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/cy/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:36:37.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/cy/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:51:23.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Soced # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Actor IPC mewn blwch tywod ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/da/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/da/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/da/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Privatliv: Privat begivenhed calendar-editable-item-privacy-icon-confidential = .alt = Privatliv: Vis kun tid og dato +calendar-editable-item-recurrence = + .alt = Gentages +calendar-editable-item-recurrence-exception = + .alt = Undtagelse for gentagelse calendar-editable-item-todo-icon-task = .alt = Opgave calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/da/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/da/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/da/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } har inviteret dig til: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Gem +calendar-invitation-panel-accept-button = Ja +calendar-invitation-panel-decline-button = Nej +calendar-invitation-panel-tentative-button = Måske +calendar-invitation-panel-reply-status = *Du har ikke besluttet dig eller svaret endnu +calendar-invitation-panel-prop-title-when = Tidspunkt: +calendar-invitation-panel-prop-title-location = Sted: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Deltagere: +calendar-invitation-panel-prop-title-description = Beskrivelse: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } ja + [DECLINED] { $count } nej + [TENTATIVE] { $count } måske + [NEEDS-ACTION] { $count } afventer + [TOTAL] { $count } deltagere + *[OTHER] { $count } andet + } diff -Nru thunderbird-91.7.0+build2/l10n/da/chat/matrix.properties thunderbird-91.8.1+build1/l10n/da/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/da/chat/matrix.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/chat/matrix.properties 2022-04-15 07:51:31.000000000 +0000 @@ -21,7 +21,12 @@ # storage, shown in the account manager. %S is one of the statuses and the # strings are combined with a pipe (|) between. options.encryption.enabled=Kryptografiske funktioner: %S +options.encryption.secretStorage=Hemmeligt lager: %S +options.encryption.crossSigning=Krydssignering: %S +options.encryption.statusOk=ok +options.encryption.statusNotOk=ikke klar # %1$S is the session ID, %2$S is the session display name +options.encryption.session=%1$S (%2$S) # LOCALIZATION NOTE (connection.*): # These will be displayed in the account manager in order to show the progress @@ -144,6 +149,7 @@ message.banned=%1$S blokerede %2$S. # Same as message.banned but with a reason. # %3$S is the reason the user was banned. +message.bannedWithReason=%1$S blokerede %2$S. Årsag: %3$S # %1$S is the name of the user who accepted the invitation. # %2$S is the name of the user who sent the invitation. message.acceptedInviteFor=%1$S accepterede invitationen for %2$S. @@ -176,11 +182,13 @@ message.kicked=%1$S smed %2$S ud. # Same as message.kicked but with a third parameter for the reason. # %3$S is the reason for the kick. +message.kickedWithReason=%1$S smed %2$S ud. Årsag: %3$S # %1$S is the name of the user who withdrew invitation. # %2$S is the name of the user whose invitation has been withdrawn. message.withdrewInvite=%1$S trak invitationen til %2$S tilbage. # Same as message.withdrewInvite but with a third paramter for the reason. # %3$S is the reason the invite was withdrawn. +message.withdrewInviteWithReason=%1$S trak invitationen til %2$S tilbage. Årsag: %3$S # %S is the name of the user who has removed the room name. message.roomName.remove=%S fjernede rummets navn. # %1$S is the name of the user who changed the room name. @@ -224,5 +232,14 @@ message.encryptionStart=Meddelelser i denne samtale er nu end to end-krypterede. # %1$S is the name of the user who sent the verification request. # %2$S is the name of the user that is receiving the verification request. +message.verification.request2=%1$S ønsker at bekræfte %2$S. # %1$S is the name of the user who cancelled the verification request. # %2$S is the reason given why the verification was cancelled. +message.verification.cancel2=%1$S annullerede bekræftelsen med årsagen: %2$S +message.verification.done=Bekræftelse afsluttet. +message.decrypting=Dekrypterer... + +# Label in the message context menu + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. diff -Nru thunderbird-91.7.0+build2/l10n/da/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/da/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/da/devtools/client/aboutdebugging.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/devtools/client/aboutdebugging.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Debugging - Opsætning - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Debugging - Runtime / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Denne { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Opsætning - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB er aktiveret - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB er deaktiveret - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Forbundet # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Afbrudt - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = Ingen enheder blev fundet - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Opret forbindelse - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Opretter forbindelse… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Forbindelse mislykkedes - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = Forbindelsen venter stadig på at blive oprettet. Kontrollér eventuelle meddelelser i mål-browseren - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = Forbindelsens tidsfrist udløb - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Venter på browser… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Fjernet - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Hjælp til debugging - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Hjælp-ikon - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Genindlæs enheder @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Opsætning - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Indstil hvilken type af forbindelse, du vil bruge til at fjern-debugge din enhed. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Brug { about-debugging-this-firefox-runtime-name } til at debugge udvidelser og service-workers i denne version af { -brand-shorter-name }. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Opret forbindelse til en enhed - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Aktivering af dette vil hente de nødvendige komponenter til USB-debugging af Android og føje dem til { -brand-shorter-name }. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = Aktiver USB-enheder - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = Deaktiver USB-enheder - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Opdaterer… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Aktiveret about-debugging-setup-usb-status-disabled = Deaktiveret about-debugging-setup-usb-status-updating = Opdaterer… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Aktiver udvikler-menuen på din Android-enhed. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Aktiver USB-debugging i udvikler-menuen på Android-enheden. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Aktiver USB-debugging i Firefox på Android-enheden. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Opret forbindelse til Android-enheden på din computer. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Har du problemer med at oprette forbindelse til USB-enheden? Fejlsøg - # Network section of the Setup page about-debugging-setup-network = .title = Netværksplacering - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Har du problemer med netværksplaceringen? Fejlsøg - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Tilføj - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = Ingen netværksplacering er blevet tilføjet endnu. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Vært - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Fjern - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Ugyldig vært "{ $host-value }". Det forventede format er "hostname:portnumber". - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Processer - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Ydelsesprofilering - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Din browser-opsætning er ikke kompatibel med service-workers. Læs mere - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = Den forbundne browser har en gammel version ({ $runtimeVersion }). Den ældste understøttede version er ({ $minVersion }). Denne opsætning understøttes ikke og kan forhindre Udviklerværktøj i at køre korrekt. Opdater den forbundne browser. Fejlsøgning - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = Denne version af Firefox kan ikke bruges til at debugge Firefox til Android (68). Vi anbefaler, at du installerer Firefox Nightly til Android for at kunne teste. Læs mere - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = Den forbundne browser er nyere ({ $runtimeVersion }, buildID { $runtimeID }) end din { -brand-shorter-name } ({ $localVersion }, buildID { $localID }). Denne opsætning understøttes ikke og kan forhindre Udviklerværktøj i at køre korrekt. Opdater Firefox. Fejlsøgning - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Afbryd - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Aktiver forbindelses-prompt - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Deaktiver forbindelses-prompt - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Profilering - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Ingenting endnu. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Inspicer - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Indlæs midlertidig tilføjelse… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = Der opstod en fejl under installering af den midlertidige tilføjelse. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Genindlæs - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Fjern - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Afslut baggrundsscript # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Vælg manifest.json-fil eller .xpi/.zip-arkiv - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Denne WebExtension har et midlertidigt ID. Learn more - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = Manifest-URL - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = Internt UUID - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Placering - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = Udvidelsens ID - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Baggrundsscript +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Kører +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Stoppet # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push .disabledTitle = Service-worker-push er i øjeblikket deaktiveret for multiproces { -brand-shorter-name } - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Start .disabledTitle = Start af service-workers er i øjeblikket deaktiveret i multiproces { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Afregistrer - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Lytter efter fetch-events - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = Lytter ikke efter fetch-events - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Kører - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Stoppet - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Registrerer - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Scope - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Push-service - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = Inspektion af service-workers er i øjeblikket deaktiveret for multiproces { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Fanebladet er ikke helt indlæst og kan ikke inspiceres - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Hoved-proces - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Hovedproces for mål-browser - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Multiproces-værktøj - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Hovedproces og indholdsprocesser for mål-browseren - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Luk besked - # Label text used for the error details of message component. about-debugging-message-details-label-error = Detaljer om fejl - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Detaljer om advarsel - # Label text used for default state of details of message component. about-debugging-message-details-label = Detaljer diff -Nru thunderbird-91.7.0+build2/l10n/da/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/da/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/da/devtools/client/compatibility.ftl 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/devtools/client/compatibility.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (eksperimentel) compatibility-issue-prefixneeded = (præfiks påkrævet) compatibility-issue-deprecated-experimental = (forældet, eksperimentel) - compatibility-issue-deprecated-prefixneeded = (forældet, præfiks påkrævet) compatibility-issue-experimental-prefixneeded = (eksperimentel, præfiks påkrævet) compatibility-issue-deprecated-experimental-prefixneeded = (forældet, eksperimentel, præfiks påkrævet) @@ -43,7 +42,14 @@ [one] { $number } forekomst *[other] { $number } forekomster } - compatibility-no-issues-found = Der blev ikke fundet problemer med kompatibilitet. compatibility-close-settings-button = .title = Luk indstillinger +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Kompatibilitetsproblemer i: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/da/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/da/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/da/devtools/client/debugger.properties 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/devtools/client/debugger.properties 2022-04-15 07:51:29.000000000 +0000 @@ -642,6 +642,16 @@ ignoreContextItem.unignore=Stop med at ignorere kilde ignoreContextItem.unignore.accesskey=S +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Ignorer linje +ignoreContextItem.ignoreLine.accesskey=I + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Ignorer ikke linje længere +ignoreContextItem.unignoreLine.accesskey=n + # LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated # with the ignore lines context menu item ignoreContextItem.ignoreLines=Ignorer linjer diff -Nru thunderbird-91.7.0+build2/l10n/da/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/da/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/da/devtools/client/netmonitor.properties 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/devtools/client/netmonitor.properties 2022-04-15 07:51:29.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=Strengen "%S" blev fjernet fra begyndelse af JSON vist nedenfor + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Query-streng: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL-parametre + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Request-headers: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Headers + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=navn + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=værdi + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Indhold + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=payload + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Request-body: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Annuller +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Ryd + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Fjern element + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Tilbage diff -Nru thunderbird-91.7.0+build2/l10n/da/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/da/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/da/devtools/client/toolbox.ftl 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/devtools/client/toolbox.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Deaktiver auto-skjul af pop op +toolbox-meatball-menu-pseudo-locale-accented = Aktiver "accented" sprog +toolbox-meatball-menu-pseudo-locale-bidi = Aktiver "bidi" sprog ## diff -Nru thunderbird-91.7.0+build2/l10n/da/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/da/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/da/devtools/client/toolbox-options.ftl 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/devtools/client/toolbox-options.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Slå remote debugging til options-enable-remote-tooltip2 = .title = Tillader at fjern-debugge denne instans af browseren. +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Aktiver tilpasset formatering +options-enable-custom-formatters-tooltip = + .title = Aktivering af denne indstilling tillader websteder at definere tilpasset formatering for DOM-objekter # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Aktiver service workers over HTTP (når værktøjerne er åbnet) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/da/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/da/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/da/devtools/client/webconsole.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/devtools/client/webconsole.properties 2022-04-15 07:51:29.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=fil +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Kopier alle beskeder +webconsole.menu.copyAllMessages.accesskey=b + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Gem alle beskeder til en fil +webconsole.menu.saveAllMessagesFile.accesskey=f + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/da/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/da/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/da/dom/chrome/dom/dom.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/dom/chrome/dom/dom.properties 2022-04-15 07:51:31.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Indtast en webadresse. FormValidationInvalidDate=Indtast en gyldig dato. FormValidationInvalidTime=Angiv et gyldigt tidspunkt. +FormValidationInvalidDateTime=Angiv en gyldig dato og et gyldigt tidspunkt. +FormValidationInvalidDateMonth=Angiv en gyldig måned. +FormValidationInvalidDateWeek=Angiv en gyldig uge. FormValidationPatternMismatch=Opfyld det forspurgte format. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Opfyld det forspurgte format: %S. diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/browser/appExtensionFields.ftl thunderbird-91.8.1+build1/l10n/da/mail/browser/appExtensionFields.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/browser/appExtensionFields.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/browser/appExtensionFields.ftl 2022-04-15 07:51:31.000000000 +0000 @@ -5,6 +5,8 @@ ## Theme names and descriptions used in the Themes panel in about:addons +# "Auto" is short for automatic. It can be localized without limitations. +extension-default-theme-name-auto = Systemtema — automatisk extension-thunderbird-compact-light-name = Lyst extension-thunderbird-compact-light-description = Et tema med et lyst farveskema. extension-thunderbird-compact-dark-name = Mørkt diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/addons.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/addons.properties 2022-04-15 07:51:29.000000000 +0000 @@ -107,7 +107,6 @@ # %S is brandShortName webextPerms.experimentWarning=Ondsindede tilføjelser kan stjæle dine private informationer eller kompromittere din computer. Installer kun tilføjelsen, hvis du stoler på udgiveren. - webextPerms.headerWithPerms=Tilføj %S? Denne udvidelse vil få tilladelse til: webextPerms.headerUnsigned=Tilføj %S? Denne udvidelse er ikke bekræftet. Ondsindede udvidelser kan stjæle dine personlige oplysninger eller bringe din computer i fare. Du bør kun tilføje den, hvis du stoler på kilden. webextPerms.headerUnsignedWithPerms=Tilføj %S? Denne udvidelse er ikke bekræftet. Ondsindede udvidelser kan stjæle dine personlige oplysninger eller bringe din computer i fare. Du bør kun tilføje den, hvis du stoler på kilden. Denne udvidelse vil få tilladelse til: @@ -226,6 +225,18 @@ # hosts for which this webextension is requesting permission. webextPerms.hostDescription.tooManySites=Tilgå dine data på #1 andet websted;Tilgå dine data på #1 andre websteder +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextSitePerms.headerWithPerms=Vil du tilføje %1$S? Denne udvidelse giver følgende tilladelser til %2$S: +webextSitePerms.headerUnsignedWithPerms=Vil du tilføje %1$S? Denne udvidelse er ikke verificeret. Ondsindede udvidelser kan stjæle dine personlige oplysninger eller kompromittere din computer. Tilføj den kun, hvis du stoler på ophavsmanden. Udvidelsen giver følgende tilladelser til %2$S: + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties +webextSitePerms.description.midi=Tilgå MIDI-enheder +webextSitePerms.description.midi-sysex=Tilgå MIDI-enheder med SysEx-understøttelse + # LOCALIZATION NOTE (webext.defaultSearch.description) # %1$S is replaced with the localized named of the extension that is asking to change the default search engine. # %2$S is replaced with the name of the current search engine @@ -235,4 +246,3 @@ webext.defaultSearchYes.accessKey=J webext.defaultSearchNo.label=Nej webext.defaultSearchNo.accessKey=N - diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/chat.properties thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/chat.properties --- thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/chat.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/chat.properties 2022-04-15 07:51:29.000000000 +0000 @@ -29,6 +29,7 @@ # sends a verification request for end-to-end encryption keys. # %S is replaced with the display name of the user or, if this is to verify a # session of yourself, a string that identifies the session. +buddy.verificationRequest.label=%S ønsker at bekræfte hinandens identiteter buddy.verificationRequest.allow.label=Start bekræftelse buddy.verificationRequest.allow.accesskey=S buddy.verificationRequest.deny.label=Afvis diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:51:29.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/mime.properties thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/mime.properties --- thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/mime.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/mime.properties 2022-04-15 07:51:29.000000000 +0000 @@ -6,55 +6,126 @@ # The following are used by libmime to emit header display in HTML # -1000=Subject - -1001=Resent-Comments - -1002=Resent-Date - -1003=Resent-Sender - -1004=Resent-From - -1005=Resent-To - -# LOCALIZATION NOTE (1006): Do not translate "CC" below. -1006=Resent-CC - -1007=Date - -1008=Sender - -1009=From - -1010=Reply-To - -1011=Organization - -1012=To - -# LOCALIZATION NOTE (1013): Do not translate "CC" below. -1013=CC - -1014=Newsgroups - -1015=Followup-To - -1016=References - -1021=Message-ID - -1023=BCC - -1026=Link to Document - -1027=Document Info: - -1028=Attachment - +# Mail subject +## @name MIME_MHTML_SUBJECT +## @loc None +1000=Emne + +# Resent-Comments +## @name MIME_MHTML_RESENT_COMMENTS +## @loc +1001=Gensendt-kommentarer + +# Resent-Date +## @name MIME_MHTML_RESENT_DATE +## @loc +1002=Gensendt-dato + +# Resent-Sender +## @name MIME_MHTML_RESENT_SENDER +## @loc +1003=Gensendt-afsender + +# Resent-From +## @name MIME_MHTML_RESENT_FROM +## @loc +1004=Gensendt-fra + +# Resent-To +## @name MIME_MHTML_RESENT_TO +## @loc +1005=Gensendt-til + +# Resent-CC +## @name MIME_MHTML_RESENT_CC +## @loc +1006=Gensendt-CC + +# Date +## @name MIME_MHTML_DATE +## @loc +1007=Dato + +# Sender +## @name MIME_MHTML_SENDER +## @loc +1008=Afsender + +# From +## @name MIME_MHTML_FROM +## @loc +1009=Fra + +# Reply-To +## @name MIME_MHTML_REPLY_TO +## @loc +1010=Svar-Til + +# Organization +## @name MIME_MHTML_ORGANIZATION +## @loc +1011=Organisation + +# To +## @name MIME_MHTML_TO +## @loc +1012=Til + +# CC +## @name MIME_MHTML_CC +## @loc +1013=Kopi (CC) + +# Newsgroups +## @name MIME_MHTML_NEWSGROUPS +## @loc +1014=Nyhedsgrupper + +# Followup-To +## @name MIME_MHTML_FOLLOWUP_TO +## @loc +1015=Opfølgning til + +# References +## @name MIME_MHTML_REFERENCES +## @loc +1016=Referencer + +# Message ID +## @name MIME_MHTML_MESSAGE_ID +## @loc +1021=Nyheds-ID + +# BCC +## @name MIME_MHTML_BCC +## @loc +1023=Skjult kopi til (BCC) + +# Link to doc +## @name MIME_MSG_LINK_TO_DOCUMENT +## @loc +1026=Link til dokument + +# Get Doc info +## @name MIME_MSG_DOCUMENT_INFO +## @loc +1027=Dokumentoplysninger: + +# Msg Attachment +## @name MIME_MSG_ATTACHMENT +## @loc +1028=Vedhæftet fil + +# default attachment name +## @name MIME_MSG_DEFAULT_ATTACHMENT_NAME +## @loc # LOCALIZATION NOTE (1040): Do not translate "%s" below. -1040=Part %s +# Place the %s where you wish the part number of the attachment to appear +1040=Del %s +# default forwarded message prefix +## @name MIME_FORWARDED_MESSAGE_HTML_USER_WROTE +## @loc 1041=-------- Original Meddelelse -------- # Partial Message Truncated diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/subscribe.properties thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/subscribe.properties --- thunderbird-91.7.0+build2/l10n/da/mail/chrome/messenger/subscribe.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/chrome/messenger/subscribe.properties 2022-04-15 07:51:30.000000000 +0000 @@ -2,7 +2,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -subscribeLabel-nntp=Vælg nyhedsgrupperne at abonnere på: +subscribeLabel-nntp=Vælg de nyhedsgrupper, du vil abonnere på: subscribeLabel-imap=Vælg mapperne at abonnere på: currentListTab-nntp.label=Nuværende gruppeliste currentListTab-nntp.accesskey=u diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/aboutDialog.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Nyheder diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/aboutImport.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/aboutImport.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -0,0 +1,70 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +import-page-title = Importer + +## Header + +import-calendar = Importer kalenderfil +export-profile = Eksporter + +## Buttons + +button-cancel = Annuller +button-back = Tilbage +button-continue = Fortsæt +button-export = Eksporter + +## Import from app steps + +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail +# Variables: +# $app (String) - The name of the app to import from +profiles-pane-title = Importer fra { $app } +profile-file-picker-dir = Vælg en profilmappe +profile-file-picker-zip = Vælg en ZIP-komprimeret fil (mindre end 2 GB) +items-pane-title = Vælg, hvad der skal importeres +items-pane-checkbox-accounts = Konti og indstillinger +items-pane-checkbox-address-books = Adressebøger +items-pane-checkbox-calendars = Kalendere +items-pane-checkbox-mail-messages = Mailmeddelelser + +## Import from address book file steps + +import-from-addr-book-file-desc = Vælg den filtype, du vil importere: +addr-book-csv-file = Komma- eller tabulatorsepareret fil (.csv, .tsv) +addr-book-ldif-file = LDIF-fil (.ldif) +addr-book-vcard-file = vCard-fil (.vcf, .vcard) +addr-book-sqlite-file = SQLite-databasefil (.sqlite) +addr-book-mab-file = Mork-databasefil (.mab) +addr-book-file-picker = Vælg en adressebogsfil +addr-book-csv-field-map-title = Match feltnavne +addr-book-directories-pane-source = Kildefil: + +## Import dialog + +progress-pane-title = Importerer +progress-pane-importing = Importerer +progress-pane-exporting = Eksporterer +progress-pane-finished-desc = Afsluttet. +progress-pane-restart-desc = Genstart for at afslutte importen. +error-pane-title = Fejl +error-message-zip-file-too-big = Den valgte ZIP-komprimerede fil er større end 2GB. Udpak først filen, og importer derefter fra den udpakkede mappe i stedet. +error-message-extract-zip-file-failed = Kunne ikke udpakke den ZIP-komprimerede fil. Udpak filen manuelt, og importer derefter fra den udpakkede mappe i stedet. + +## element + +csv-source-first-record = Første post +csv-source-second-record = Anden post +csv-target-field = Adressebogsfelt + +## Export tab + +export-open-profile-folder = Åbn profilmappen +export-file-picker = Eksporter til en ZIP-komprimeret fil +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/aboutSupportChat.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/aboutSupportChat.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/aboutSupportChat.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/aboutSupportChat.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -0,0 +1,11 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +chat-title = Chat-konti +chat-table-heading-account = ID +chat-table-heading-protocol = Protokol +chat-table-heading-name = Navn +chat-table-heading-actions = Handlinger +chat-table-copy-debug-log = Kopier debug-log + .title = Kopier fejl og anden logning fra denne chatkonto til udklipsholderen. Kan indeholde personlige oplysninger som chatbeskeder. diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountCentral.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountCentral.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountCentral.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountCentral.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -4,7 +4,6 @@ account-central-title = Velkommen til { -brand-full-name } account-settings = Kontoindstillinger - # $accounts (Number) - the number of configured accounts setup-title = { $accounts -> @@ -13,53 +12,40 @@ } about-title = Om { -brand-full-name } resources-title = Resurser - release-notes = .title = Om { -brand-full-name } - email-label = Mail .aria-label = Tilknyt din eksisterende mailkonto email-description = { -brand-short-name } giver dig mulighed for at oprette forbindelse til din eksisterende mailkonto, så du nemt kan læse dine mails i programmet. - calendar-label = Kalender .aria-label = Opret en ny kalender calendar-description = { -brand-short-name } giver dig mulighed for at håndtere og holde styr på begivenheder. Hvis du opretter forbindelse til en fjernkalender, vil alle dine begivenheder være synkroniseret på tværs af alle dine enheder. - chat-label = Chat .aria-label = Opret forbindelse til din chat-konto chat-description = { -brand-short-name } giver dig mulighed for at oprette forbindelse til forskellige chat-konti og understøtter forskellige platforme. - filelink-label = Filelink .aria-label = Indstil Filelink filelink-description = { -brand-short-name } giver dig mulighed for at oprette en praktisk filelink-cloud-konto, så du nemt kan sende store filer. - addressbook-label = Adressebog .aria-label = Opret en ny adressebog addressbook-description = { -brand-short-name } giver dig mulighed for at organisere alle dine kontakter i en adressebog. Du kan også oprette forbindelse til en ekstern adressebog, så alle dine kontakter er synkroniserede. - feeds-label = Feeds .aria-label = Opret forbindelse til feeds feeds-description = { -brand-short-name } giver dig mulighed for at oprette forbindelse til RSS/Atom-feeds og få nyheder og opdateringer fra hele verden. - newsgroups-label = Nyhedsgrupper .aria-label = Opret forbindelse til en nyhedsgruppe newsgroups-description = { -brand-short-name } giver dig mulighed for at oprette forbindelse til alle de nyhedsgrupper, du ønsker. - import-title = Importer fra et andet program import-paragraph = { -brand-short-name } giver dig mulighed for at importere mails, adressebogsindhold, feed-abonnementer, indstillinger og/eller filtre fra andre mailprogrammer og almindelige adressebogsformater. - +import-paragraph2 = { -brand-short-name } giver dig mulighed for at importere mails, adressebogsindhold, feed-abonnementer, indstillinger og/eller filtre fra andre mailprogrammer og almindelige adressebogsformater. import-label = Importer .aria-label = Importer data fra andre programmer - about-paragraph = Thunderbird er det førende platformsuafhængige mail- og kalenderprogram baseret på open source. Programmet er gratis, både til private og virksomheder. Vi ønsker, at Thunderbird fortsat skal være sikker og blive endnu bedre. Et bidrag hjælper os med at ansætte udviklere, betale for den bagvedliggende infrastruktur og med fortsat at forbedre Thunderbird. - about-paragraph-consider-donation = Thunderbird er økonomisk støttet af vores brugere. Hvis du er glad for Thunderbird, så hjælp os gerne med et bidrag. Ved at give et bidrag er du med til at sikre, at Thunderbird også bliver udviklet i fremtiden. - explore-link = Udforsk funktioner support-link = Support involved-link = Vær med developer-link = Udviklerdokumentation - read = Læs meddelelser compose = Skriv en ny meddelelse search = Søg i meddelelser diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountcreation/accountSetup.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountcreation/accountSetup.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountcreation/accountSetup.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountcreation/accountSetup.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -7,65 +7,49 @@ ## Header account-setup-title = Tilføj din eksisterende mailadresse - account-setup-description = For at bruge din nuværende mailadresse, skal du indtaste dine login-oplysninger. - account-setup-secondary-description = { -brand-product-name } vil automatisk søge efter en anbefalet serverkonfiguration, der virker. - account-setup-success-title = Kontoen blev oprettet - account-setup-success-description = Du kan nu bruge denne konto med { -brand-short-name }. - account-setup-success-secondary-description = Du kan forbedre oplevelsen ved at oprette forbindelse til relaterede tjenester og konfigurere avancerede kontoindstillinger. ## Form fields account-setup-name-label = Dit fulde navn .accesskey = D - # Note: "John Doe" is a multiple-use name that is used when the true name of a person is unknown. We use this fake name as an input placeholder. Translators should update this to reflect the placeholder name of their language/country. account-setup-name-input = .placeholder = Jane Hansen - account-setup-name-info-icon = .title = Dit navn som andre skal se det - - account-setup-name-warning-icon = .title = Indtast dit navn - account-setup-email-label = Mailadresse .accesskey = M - account-setup-email-input = .placeholder = jane.hansen@eksempel.dk - account-setup-email-info-icon = .title = Din eksisterende mailadresse - account-setup-email-warning-icon = .title = Ugyldig mailadresse - account-setup-password-label = Adgangskode .accesskey = d .title = Valgfri, vil kun blive brugt til at validere brugernavnet - account-provisioner-button = Få en ny mailadresse .accesskey = F - account-setup-password-toggle = .title = Vis/skjul adgangskode - +account-setup-password-toggle-show = + .title = Vis adgangskode i klartekst +account-setup-password-toggle-hide = + .title = Skjul adgangskode account-setup-remember-password = Husk adgangskode .accesskey = H - account-setup-exchange-label = Dit login .accesskey = l - # YOURDOMAIN refers to the Windows domain in ActiveDirectory. yourusername refers to the user's account name in Windows. account-setup-exchange-input = .placeholder = DITDOMÆNE\ditbrugernavn - # Domain refers to the Windows domain in ActiveDirectory. We mean the user's login in Windows at the local corporate network. account-setup-exchange-info-icon = .title = Domæne-login @@ -74,62 +58,39 @@ account-setup-button-cancel = Annuller .accesskey = A - account-setup-button-manual-config = Manuel opsætning .accesskey = o - account-setup-button-stop = Stop .accesskey = S - account-setup-button-retest = Afprøv konfigurationen .accesskey = ø - account-setup-button-continue = Fortsæt .accesskey = F - account-setup-button-done = Opret konto .accesskey = O ## Notifications account-setup-looking-up-settings = Undersøger konfiguration… - account-setup-looking-up-settings-guess = Undersøger konfiguration: Prøver almindelige servernavne… - account-setup-looking-up-settings-half-manual = Undersøger konfiguration: Forespørger serveren… - account-setup-looking-up-disk = Undersøger konfiguration: { -brand-short-name }-installation… - account-setup-looking-up-isp = Undersøger konfiguration: Mailudbyder… - # Note: Do not translate or replace Mozilla. It stands for the public project mozilla.org, not Mozilla Corporation. The database is a generic, public domain facility usable by any client. account-setup-looking-up-db = Undersøger konfiguration: Mozillas database over mailudbydere… - account-setup-looking-up-mx = Undersøger konfiguration: Indgående maildomæne… - account-setup-looking-up-exchange = Undersøger konfiguration: Exchange-server… - account-setup-checking-password = Kontrollerer adgangskode… - account-setup-installing-addon = Henter og installerer tilføjelse… - account-setup-success-half-manual = Følgende indstillinger blev fundet ved at forespørge serveren: - account-setup-success-guess = Konfiguration fundet ved at prøve almindelige servernavne. - account-setup-success-guess-offline = Du er offline. Vi har gættet på nogle af indstillingerne, men du skal selv angive de rigtige indstillinger for at oprette kontoen. - account-setup-success-password = Adgangskode OK - account-setup-success-addon = Tilføjelsen blev installeret - # Note: Do not translate or replace Mozilla. It stands for the public project mozilla.org, not Mozilla Corporation. The database is a generic, public domain facility usable by any client. account-setup-success-settings-db = Konfiguration fundet i Mozillas database over mailudbydere. - account-setup-success-settings-disk = Konfiguration fundet på { -brand-short-name }-installation. - account-setup-success-settings-isp = Konfiguration fundet hos mailudbyderen. - # Note: Microsoft Exchange is a product name. account-setup-success-settings-exchange = Fandt konfiguration for en Microsoft Exchange-server. @@ -137,33 +98,21 @@ account-setup-step1-image = .title = Indledende opsætning - account-setup-step2-image = .title = Indlæser… - account-setup-step3-image = .title = Konfiguration fundet - account-setup-step4-image = .title = Forbindelsesfejl - account-setup-step5-image = .title = Konto oprettet - account-setup-privacy-footnote2 = Dine login-oplysninger vil kun blive gemt lokalt på din computer. - account-setup-selection-help = Ved du ikke, hvad du skal vælge? - account-setup-selection-error = Har du brug for hjælp? - account-setup-success-help = Usikker på, hvad du skal nu? - account-setup-documentation-help = Dokumentation om opsætning - account-setup-forum-help = Supportforum - account-setup-privacy-help = Privatlivspolitik - account-setup-getting-started = Sådan kommer du i gang ## Results area @@ -175,41 +124,25 @@ [one] Tilgængelig konfiguration *[other] Tilgængelige konfigurationer } - # Note: IMAP is the name of a protocol. account-setup-result-imap = IMAP - account-setup-result-imap-description = Hold dine mapper og meddelelser synkroniseret på din server - # Note: POP3 is the name of a protocol. account-setup-result-pop = POP3 - account-setup-result-pop-description = Hold dine mapper og meddelelser på din computer - # Note: Exchange is the name of a product. account-setup-result-exchange = Exchange - # Note: Exchange, Office365 are the name of products. account-setup-result-exchange2-description = Brug Microsoft Exchange-serveren eller Office365-cloudtjenester - account-setup-incoming-title = Indgående - account-setup-outgoing-title = Udgående - account-setup-username-title = Brugernavn - account-setup-exchange-title = Server - account-setup-result-smtp = SMTP - account-setup-result-no-encryption = Ingen kryptering - account-setup-result-ssl = SSL/TLS - account-setup-result-starttls = STARTTLS - account-setup-result-outgoing-existing = Brug eksisterende udgående SMTP-server - # Variables: # $incoming (String): The email/username used to log into the incoming server # $outgoing (String): The email/username used to log into the outgoing server @@ -219,81 +152,55 @@ # Note: The reference to "janedoe" (Jane Doe) is the name of an example person. You will want to translate it to whatever example persons would be named in your language. In the example, AD is the name of the Windows domain, and this should usually not be translated. account-setup-credentials-incomplete = Godkendelse mislykkedes. Enten er de indtastede oplysninger forkerte, eller der skal bruges et separat brugernavn for at logge ind. Dette er normalt brugernavnet til dit Windows-domæne med eller uden domænet (for eksempel janehansen eller AD\\janehansen) - account-setup-credentials-wrong = Godkendelse mislykkedes. Kontroller brugernavn og adgangskode - account-setup-find-settings-failed = { -brand-short-name } kunne ikke finde indstillinger til din mailkonto - account-setup-exchange-config-unverifiable = Konfigurationen kunne ikke bekræftes. Hvis brugernavn og adgangskode er indtastet korrekt, skyldes det sandsynligvis, at serveradministratoren har deaktiveret den valgte indstilling for din konto. Prøv at vælge en anden protokol. +account-setup-provisioner-error = Der opstod en fejl under opsætningen af din nye konto i { -brand-short-name }. Prøv at opsætte din konto manuelt med dine log in-oplysninger. ## Manual configuration area account-setup-manual-config-title = Serverindstillinger - account-setup-incoming-server-legend = Indgående server - account-setup-protocol-label = Protokol: - protocol-imap-option = { account-setup-result-imap } - protocol-pop-option = { account-setup-result-pop } - protocol-exchange-option = { account-setup-result-exchange } - account-setup-hostname-label = Værtsnavn: - account-setup-port-label = Port: .title = Sæt portnummeret til 0 for autodetektion - account-setup-auto-description = { -brand-short-name } forsøger automatisk at udfylde tomme felter. - account-setup-ssl-label = Forbindelsessikkerhed: - account-setup-outgoing-server-legend = Udgående server ## Incoming/Outgoing SSL Authentication options ssl-autodetect-option = Find automatisk - ssl-no-authentication-option = Ingen godkendelse - ssl-cleartext-password-option = Almindelig adgangskode - ssl-encrypted-password-option = Krypteret adgangskode ## Incoming/Outgoing SSL options ssl-noencryption-option = Ingen - account-setup-auth-label = Godkendelsesmetode: - account-setup-username-label = Brugernavn: - account-setup-advanced-setup-button = Avanceret konfiguration .accesskey = v ## Warning insecure server dialog account-setup-insecure-title = Advarsel! - account-setup-insecure-incoming-title = Indstillinger for indgående: - account-setup-insecure-outgoing-title = Indstillinger for udgående: - # Variables: # $server (String): The name of the hostname of the server the user was trying to connect to. account-setup-warning-cleartext = { $server } bruger ikke kryptering. - account-setup-warning-cleartext-details = Usikre mailservere benytter ikke kryptering til at beskytte din adgangskode og indholdet i dine mails. Ved at forbinde til denne server risikerer du at få afluret din adgangskode og indholdet i dine mails. - account-setup-insecure-server-checkbox = Jeg accepterer risikoen .accesskey = a - account-setup-insecure-description = { -brand-short-name } lader dig bruge mailkontoen med den angivne konfiguration. Du bør dog kontakte din administrator eller mailudbyder angående disse usikre forbindelsesindstillinger. Se Thunderbirds FAQ for yderligere oplysninger. - insecure-dialog-cancel-button = Rediger indstillinger .accesskey = R - insecure-dialog-confirm-button = Bekræft .accesskey = B @@ -302,53 +209,45 @@ # Variables: # $domain (String): The name of the server where the configuration was found, e.g. rackspace.com. exchange-dialog-question = { -brand-short-name } fandt oplysninger om dine kontoindstillinger på { $domain }. Vil du fortsætte og indsende dine login-informationer? - exchange-dialog-confirm-button = Login - exchange-dialog-cancel-button = Annuller ## Dismiss account creation dialog +exit-dialog-title = Ingen mailkonto konfigureret +exit-dialog-description = Er du sikker på, at du vil annullere opsætningen? { -brand-short-name } kan stadig bruges uden en mailkonto, men mange funktioner vil ikke være tilgængelige. +account-setup-no-account-checkbox = Brug { -brand-short-name } uden en mailkonto + .accesskey = B +exit-dialog-cancel-button = Fortsæt opsætningen + .accesskey = F +exit-dialog-confirm-button = Afslut opsætningen + .accesskey = A + ## Alert dialogs account-setup-creation-error-title = Kunne ikke oprette konto - account-setup-error-server-exists = Indgående server er allerede oprettet. - account-setup-confirm-advanced-title = Bekræft avanceret opsætning - account-setup-confirm-advanced-description = Denne besked lukkes og en konto med de aktuelle indstillinger bliver oprettet, også selvom de måske er forkerte. Ønsker du at fortsætte? ## Addon installation section account-setup-addon-install-title = Installer - account-setup-addon-install-intro = En tilføjelse fra tredjepart kan give dig adgang til din mailkonto på denne server: - account-setup-addon-no-protocol = Denne mailserver understøtter desværre ikke åbne protokoller. { account-setup-addon-install-intro } ## Success view account-setup-settings-button = Kontoindstillinger - account-setup-encryption-button = End to end-kryptering - account-setup-signature-button = Tilføj en signatur - account-setup-dictionaries-button = Hent ordbøger - account-setup-address-book-carddav-button = Opret forbindelse til en CardDAV-adressebog - account-setup-address-book-ldap-button = Opret forbindelse til en LDAP-adressebog - account-setup-calendar-button = Opret forbindelse til en fjernkalender - account-setup-linked-services-title = Tilslut dine tilknyttede tjenester - account-setup-linked-services-description = { -brand-short-name } fandt andre tjenester, der er knyttet til din mailkonto. - account-setup-no-linked-description = Konfigurer andre tjenester for at få mest muligt ud af din { -brand-short-name }-oplevelse. - # Variables: # $count (Number) - The number of address books found during autoconfig. account-setup-found-address-books-description = @@ -356,7 +255,6 @@ [one] { -brand-short-name } fandt en adressebog, der er knyttet til din mailkonto. *[other] { -brand-short-name } fandt { $count } adressebøger, der er knyttet til din mailkonto. } - # Variables: # $count (Number) - The number of calendars found during autoconfig. account-setup-found-calendars-description = @@ -364,62 +262,41 @@ [one] { -brand-short-name } fandt en kalender, der er knyttet til din mailkonto. *[other] { -brand-short-name } fandt { $count } kalendere, der er knyttet til din mailkonto. } - account-setup-button-finish = Afslut .accesskey = A - account-setup-looking-up-address-books = Undersøger adressebøger… - account-setup-looking-up-calendars = Undersøger kalendere… - account-setup-address-books-button = Adressebøger - account-setup-calendars-button = Kalendere - account-setup-connect-link = Opret forbindelse - account-setup-existing-address-book = Forbundet .title = Der er allerede forbindelse til adressebogen - account-setup-existing-calendar = Forbundet .title = Der er allerede forbindelse til kalenderen - account-setup-connect-all-calendars = Opret forbindelse til alle kalendere - account-setup-connect-all-address-books = Opret forbindelse til alle adressebøger ## Calendar synchronization dialog calendar-dialog-title = Opret forbindelse til kalender - calendar-dialog-cancel-button = Annuller .accesskey = A - calendar-dialog-confirm-button = Opret forbindelse .accesskey = f - account-setup-calendar-name-label = Navn - account-setup-calendar-name-input = .placeholder = Min kalender - account-setup-calendar-color-label = Farve - account-setup-calendar-refresh-label = Opdater - account-setup-calendar-refresh-manual = Manuelt - account-setup-calendar-refresh-interval = { $count -> [one] Hvert minut *[other] Hvert { $count }. minut } - account-setup-calendar-read-only = Skrivebeskyttet .accesskey = S - account-setup-calendar-show-reminders = Vis alarmer .accesskey = V - account-setup-calendar-offline-support = Offline-understøttelse .accesskey = O diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountManager.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountManager.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountManager.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountManager.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -3,6 +3,8 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. open-preferences-sidebar-button = { -brand-short-name }-indstillinger - +open-preferences-sidebar-button2 = { -brand-short-name }-indstillinger open-addons-sidebar-button = Tilføjelser og temaer - +account-action-add-newsgroup-account = + .label = Tilføj nyhedsgruppekonto + .accesskey = n diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountProvisioner.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountProvisioner.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/accountProvisioner.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/accountProvisioner.ftl 2022-04-15 07:51:31.000000000 +0000 @@ -0,0 +1,47 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +account-provisioner-tab-title = Få en ny e-mailadresse fra en tjenesteudbyder +provisioner-searching-icon = + .alt = Søger… +account-provisioner-title = Lav en ny e-mailadresse +account-provisioner-description = Brug vores betroede partnere til at få en ny privat og sikker e-mailadresse. +account-provisioner-start-help = De anvendte søgetermer sendes til { -vendor-short-name } (privatlivspolitik) og tredjeparts mailudbydere mailfence.com (privatlivspolitik, betingelser for brug) og gandi.net (privatlivspolitik, betingelser for brug) for at finde tilgængelige mailadresser. +account-provisioner-mail-account-title = Køb en ny mailadresse +account-provisioner-domain-title = Køb en e-mail og dit eget domæne + +## Forms + +account-provisioner-search-button = Søg +account-provisioner-button-cancel = Annuller +account-provisioner-button-existing = Brug en eksisterende mailkonto +account-provisioner-button-back = Gå tilbage + +## Notifications + +account-provisioner-fetching-provisioners = Henter udbydere... +account-provisioner-searching-email = Søger efter tilgængelige mailkonti... +account-provisioner-searching-domain = Søger efter tilgængelige domæner... + +## Illustrations + +account-provisioner-step1-image = + .title = Vælg hvilken konto der skal oprettes + +## Search results + +# Variables: +# $count (Number) - The number of domains found during search. +account-provisioner-results-title = + { $count -> + [one] En tilgængelig adresse fundet for: + *[other] { $count } tilgængelige adresser fundet for: + } +account-provisioner-mail-results-caption = Du kan prøve at søge på aliasser eller med andre søgeord for at finde flere mailadresser. +account-provisioner-domain-results-caption = Du kan prøve at søge på aliasser eller med andre søgeord for at finde flere adresser. +account-provisioner-free-account = Gratis +account-provision-price-per-year = { $pris } om året +account-provisioner-all-results-button = Vis alle resultater +account-provisioner-open-in-tab-img = + .title = Åbn i et nyt faneblad diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Ny CardDAV-adressebog - +carddav-window-title = Ny CardDAV-adressebog carddav-dialog = .buttonlabelaccept = Fortsæt .buttonaccesskeyaccept = F - carddav-username-label = .value = Brugernavn: .accesskey = B - carddav-location-label = .value = Placering .accesskey = P carddav-location = .default-placeholder = URL eller værtsnavn på adressebogs-serveren - carddav-loading = Henter indstillinger… carddav-known-incompatible = { $url } er kendt for at være inkompatibel med { -brand-short-name }. carddav-connection-error = Kunne ikke forbinde. carddav-none-found = Fandt ingen adressebøger at tilføje for den pågældende konto. carddav-already-added = Alle adressebøger for den pågældende konto er allerede tilføjet. - carddav-available-books = Tilgængelige adressebøger: diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -16,22 +16,26 @@ .label = Ny kontakt about-addressbook-toolbar-new-list = .label = Ny mailingliste +about-addressbook-toolbar-import = + .label = Importer ## Books all-address-books = Alle adressebøger - about-addressbook-books-context-properties = .label = Egenskaber about-addressbook-books-context-synchronize = .label = Synkroniser about-addressbook-books-context-print = .label = Udskriv… +about-addressbook-books-context-export = + .label = Eksporter… about-addressbook-books-context-delete = .label = Slet about-addressbook-books-context-remove = .label = Fjern - +about-addressbook-books-context-startup-default = + .label = Standardmappe ved start about-addressbook-confirm-delete-book-title = Slet adressebog # Variables: # $name (String) - Name of the address book to be deleted. @@ -49,17 +53,14 @@ .placeholder = Søg i { $name } about-addressbook-search-all = .placeholder = Søg i alle adressebøger - about-addressbook-sort-button = .title = Skift listens rækkefølge - about-addressbook-name-format-display = .label = Vist navn about-addressbook-name-format-firstlast = .label = Fornavn Efternavn about-addressbook-name-format-lastfirst = .label = Efternavn, fornavn - about-addressbook-sort-name-ascending = .label = Sorter efter navn (A > Å) about-addressbook-sort-name-descending = @@ -68,7 +69,8 @@ .label = Sorter efter mailadresse (A > Å) about-addressbook-sort-email-descending = .label = Sorter efter mailadresse (Å > A) - +about-addressbook-cards-context-write = + .label = Skriv about-addressbook-confirm-delete-mixed-title = Slet kontakter og lister # Variables: # $count (Number) - The number of contacts and lists to be deleted. Always greater than 1. @@ -125,9 +127,20 @@ about-addressbook-begin-edit-contact-button = Rediger about-addressbook-cancel-edit-contact-button = Annuller about-addressbook-save-edit-contact-button = Gem - about-addressbook-details-email-addresses-header = Mailadresser about-addressbook-details-phone-numbers-header = Telefonnumre about-addressbook-details-home-address-header = Hjemmeadresse about-addressbook-details-work-address-header = Arbejdsadresse about-addressbook-details-other-info-header = Anden information +about-addressbook-unsaved-changes-prompt-title = Ugemte ændringer +about-addressbook-unsaved-changes-prompt = Vil du gemme dine ændringer, inden du forlader redigeringsvisningen? + +# Photo dialog + +about-addressbook-photo-drop-target = Slip eller indsæt et billede her, eller klik for at vælge en fil. +about-addressbook-photo-drop-loading = Indlæser billede... +about-addressbook-photo-drop-error = Billedet kunne ikke indlæses. +about-addressbook-photo-filepicker-title = Vælg en billedfil +about-addressbook-photo-discard = Kassér eksisterende billede +about-addressbook-photo-cancel = Fortryd +about-addressbook-photo-save = Gem diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/addressbook/fieldMapImport.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/addressbook/fieldMapImport.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/addressbook/fieldMapImport.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/addressbook/fieldMapImport.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -4,10 +4,9 @@ import-ab-csv-window = .title = Importer adressebog fra tekstfil - +import-ab-csv-dialog-title = Importer adressebog fra tekstfil # $recordNumber (Number) - The current record number of the preview data. import-ab-csv-preview-record-number = Forhåndsvisning af dataimport for post { $recordNumber } - import-ab-csv-dialog = .buttonlabelaccept = Importer .buttonaccesskeyaccept = I diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/chat.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/chat.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/chat.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/chat.ftl 2022-04-15 07:51:31.000000000 +0000 @@ -4,18 +4,36 @@ chat-joining-chat-icon2 = .alt = Joiner chat - chat-left-chat-icon2 = .alt = Forlod chat - chat-participant-owner-role-icon2 = .alt = Ejer - chat-participant-administrator-role-icon2 = .alt = Administrator - chat-participant-moderator-role-icon2 = .alt = Moderator - chat-participant-voiced-role-icon2 = .alt = Deltager kan skrive beskeder +chat-verify-identity = + .label = Bekræft identitet + .accesskey = I +chat-identity-verified = + .label = Identiteten er allerede bekræftet +chat-buddy-identity-status = Tillid til kryptering +chat-buddy-identity-status-verified = Bekræftet +chat-buddy-identity-status-unverified = Ubekræftet + +## Conversation invite notification box + +# This string appears in a notification bar at the top of the Contacts window +# when someone invited the user to a multi user chat conversation, to request +# the user to confirm they want to join the chat. +# Variables: +# $conversation (String) - Name of the conversation the user is invited to. +chat-conv-invite-label = Du er blevet inviteret til at chatte i { $conversation } +chat-conv-invite-accept = + .label = Bekræft + .accesskey = B +chat-conv-invite-deny = + .label = Afvis + .accesskey = A diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/chat-verifySession.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/chat-verifySession.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/chat-verifySession.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/chat-verifySession.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -0,0 +1,14 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +verify-window-title = Bekræft identitet +# Variables: +# $subject (String) - a human readable identifier for the other side of the verification flow. +verify-window-subject-title = Bekræft identiteten af { $subject } +verify-dialog = + .buttonlabelaccept = De matcher + .buttonaccesskeyaccept = D + .buttonlabelextra2 = De matcher ikke + .buttonaccesskeyextra2 = e +challenge-label = Bekræft at den viste streng matcher den, der er vist i den anden ende. diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/exportDialog.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/exportDialog.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/exportDialog.ftl 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/exportDialog.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -3,21 +3,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export-dialog-brand-name = { -brand-product-name } - -export-dialog-window = - .title = Eksporter - +export-dialog-title = Eksporter export-dialog = .buttonlabelaccept = Næste - export-dialog-button-finish = Afslut - export-dialog-file-picker = Eksporter til en ZIP-komprimeret fil - -export-dialog-desc1 = Eksporter mailkonti, beskeder, adressebøger og indstillinger til en ZIP-komprimeret fil. - +export-dialog-description1 = Eksporter mailkonti, mailbeskeder, adressebøger og indstillinger til en ZIP-komprimeret fil. export-dialog-desc2 = Hvis du får brug for det, kan du importere den ZIP-komprimerede fil for at gendanne din profil. - export-dialog-exporting = Eksporterer… - export-dialog-exported = Eksporteret! diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/importDialog.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/importDialog.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/importDialog.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/importDialog.ftl 2022-04-15 07:51:31.000000000 +0000 @@ -4,9 +4,17 @@ # Short name of the import module thunderbird-import-name = Thunderbird - # Description of the import module thunderbird-import-description = Importer mail fra en Thunderbird-profilmappe. - +import-from-thunderbird-zip = + .label = Thunderbird (eksporteret backup af profil; ZIP-komprimeret fil mindre end 2GB) + .accesskey = k +import-from-thunderbird-dir = + .label = Thunderbird (profilmappe) + .accesskey = p import-select-profile-zip = Vælg en zip-komprimeret profilmappe - +zip-file-too-big-title = Den ZIP-komprimerede fil er for stor +zip-file-too-big-message = Den valgte ZIP-komprimerede fil er større end 2 GB. Udpak den først, og importer derefter fra den udpakkede mappe i stedet. +wizardpage-failed = + .label = Import mislykkedes +wizardpage-failed-message = Import mislykkedes uventet. Flere oplysninger er muligvis tilgængelige i fejlkonsollen. diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/menubar.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/menubar.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -3,8 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. -## View Menu - ## Tools Menu # Since v89 we dropped the platforms distinction between Options or Preferences @@ -12,7 +10,9 @@ menu-tools-preferences = .label = Indstillinger .accesskey = n - +menu-tools-settings = + .label = Indstillinger + .accesskey = n menu-addons-and-themes = .label = Tilføjelser og temaer .accesskey = T @@ -22,11 +22,9 @@ menu-help-enter-troubleshoot-mode = .label = Fejlsøgnings-tilstand… .accesskey = F - menu-help-exit-troubleshoot-mode = .label = Slå fejlsøgnings-tilstand fra .accesskey = S - menu-help-more-troubleshooting-info = .label = Mere teknisk information .accesskey = t @@ -57,18 +55,18 @@ mail-uidensity-label = .label = Tæthed .accesskey = T - mail-uidensity-compact = .label = Kompakt .accesskey = K - mail-uidensity-normal = .label = Normal .accesskey = N - mail-uidensity-touch = .label = Touch .accesskey = T ## File +file-new-newsgroup-account = + .label = Nyhedsgruppekonto… + .accesskey = y diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -3,12 +3,11 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Addressing widget +## Addressing widget # $type (String) - the type of the addressing row remove-address-row-button = .title = Fjern feltet { $type } - # $type (String) - the type of the addressing row # $count (Number) - the number of address pills currently present in the addressing row address-input-type-aria-label = @@ -17,7 +16,6 @@ [one] { $type } med én adresse, brug venstre piletast for at flytte fokus til den. *[other] { $type } med { $count } adresser, brug venstre piletast for at flytte fokus til dem. } - # $email (String) - the email address # $count (Number) - the number of address pills currently present in the addressing row pill-aria-label = @@ -25,67 +23,57 @@ [one] { $email }: tryk på Enter-tasten for at redigere, Tryk på Slet-tasten for at fjerne. *[other] { $email }, 1 af { $count }: tryk på Enter-tasten for at redigere, Tryk på Slet-tasten for at fjerne. } - # $email (String) - the email address pill-tooltip-invalid-address = { $email } er ikke en gyldig mailadresse - # $email (String) - the email address pill-tooltip-not-in-address-book = { $email } er ikke i din adressebog - pill-action-edit = .label = Rediger adresse .accesskey = R - pill-action-move-to = .label = Flyt til Til .accesskey = T - pill-action-move-cc = .label = Flyt til Kopi til (Cc) .accesskey = C - pill-action-move-bcc = .label = Flyt til Skjult kopi til (Bcc) .accesskey = B - pill-action-expand-list = .label = Udvid liste .accesskey = U -# Attachment widget +## Attachment widget ctrl-cmd-shift-pretty-prefix = { PLATFORM() -> [macos] ⇧ ⌘{ " " } *[other] Ctrl+Shift+ } - trigger-attachment-picker-key = A toggle-attachment-pane-key = Æ - menuitem-toggle-attachment-pane = .label = Ruden Vedhæftede filer .accesskey = æ .acceltext = { ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key } - toolbar-button-add-attachment = .label = Vedhæft .tooltiptext = Vedhæft en fil ({ ctrl-cmd-shift-pretty-prefix }{ trigger-attachment-picker-key }) - add-attachment-notification-reminder = .label = Vedhæft fil… .tooltiptext = { toolbar-button-add-attachment.tooltiptext } - +add-attachment-notification-reminder2 = + .label = Vedhæft fil… + .accesskey = V + .tooltiptext = { toolbar-button-add-attachment.tooltiptext } menuitem-attach-files = .label = Fil(er) .accesskey = F .acceltext = { ctrl-cmd-shift-pretty-prefix }{ trigger-attachment-picker-key } - context-menuitem-attach-files = .label = Vedhæft fil(er)… .accesskey = V .acceltext = { ctrl-cmd-shift-pretty-prefix }{ trigger-attachment-picker-key } - # $count (Number) - the number of attachments in the attachment bucket attachment-bucket-count = .value = @@ -94,26 +82,32 @@ *[other] { $count } vedhæftede filer } .accesskey = æ - expand-attachment-pane-tooltip = .tooltiptext = Vis ruden Vedhæftede filer ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) - collapse-attachment-pane-tooltip = .tooltiptext = Skjul ruden Vedhæftede filer ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) - +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } vedhæftet fil + *[other] { $count } vedhæftede filer + } +attachment-area-show = + .title = Vis ruden Vedhæftede filer ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +attachment-area-hide = + .title = Skjul ruden Vedhæftede filer ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) drop-file-label-attachment = { $count -> [one] Tilføj som vedhæftet fil *[other] Tilføj som vedhæftede filer } - drop-file-label-inline = { $count -> [one] Indsæt som en del af meddelelsen *[other] Indsæt som en del af meddelelsen } -# Reorder Attachment Panel +## Reorder Attachment Panel move-attachment-first-panel-button = .label = Flyt forrest @@ -123,74 +117,120 @@ .label = Flyt til højre move-attachment-last-panel-button = .label = Flyt bagerst - button-return-receipt = .label = Kvittering .tooltiptext = Bed om en kvittering for modtagelse af denne meddelelse -# Encryption +## Encryption + +message-to-be-signed-icon = + .alt = Underskriv meddelelse digitalt +message-to-be-encrypted-icon = + .alt = Krypter meddelelse -# Addressing Area +## Addressing Area to-compose-address-row-label = .value = Til - # $key (String) - the shortcut key for this field to-compose-show-address-row-menuitem = .label = Feltet { to-compose-address-row-label.value } .accesskey = T .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } - to-compose-show-address-row-label = .value = { to-compose-address-row-label.value } .tooltiptext = Vis feltet { to-compose-address-row-label.value } ({ to-compose-show-address-row-menuitem.acceltext }) - cc-compose-address-row-label = .value = Kopi til (Cc) - # $key (String) - the shortcut key for this field cc-compose-show-address-row-menuitem = .label = Feltet { cc-compose-address-row-label.value } .accesskey = C .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } - cc-compose-show-address-row-label = .value = { cc-compose-address-row-label.value } .tooltiptext = Vis feltet { cc-compose-address-row-label.value } ({ cc-compose-show-address-row-menuitem.acceltext }) - bcc-compose-address-row-label = .value = Skjult kopi til (Bcc) - # $key (String) - the shortcut key for this field bcc-compose-show-address-row-menuitem = .label = Feltet { bcc-compose-address-row-label.value } .accesskey = B .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } - bcc-compose-show-address-row-label = .value = { bcc-compose-address-row-label.value } .tooltiptext = Vis feltet { bcc-compose-address-row-label.value } ({ bcc-compose-show-address-row-menuitem.acceltext }) - # $count (Number) - the count of addresses in the "To" and "Cc" fields. many-public-recipients-info = De { $count } modtagere i Til og Kopi til (Cc) vil kunne se hinandens adresser. Du kan undgå at vise modtagerne ved at bruge Skjult kopi til (Bcc) i stedet. - - +to-address-row-label = + .value = Til +# $key (String) - the shortcut key for this field +show-to-row-main-menuitem = + .label = Feltet Til + .accesskey = T + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } +# No acceltext should be shown. +# The label should match the show-to-row-button text. +show-to-row-extra-menuitem = + .label = Til + .accesskey = T +# $key (String) - the shortcut key for this field +show-to-row-button = Til + .title = Vis feltet Til ({ ctrl-cmd-shift-pretty-prefix }{ $key }) +cc-address-row-label = + .value = Kopi til (Cc) +# $key (String) - the shortcut key for this field +show-cc-row-main-menuitem = + .label = Feltet Kopi til (Cc) + .accesskey = o + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } +# No acceltext should be shown. +# The label should match the show-cc-row-button text. +show-cc-row-extra-menuitem = + .label = Kopi til (Cc) + .accesskey = C +# $key (String) - the shortcut key for this field +show-cc-row-button = Kopi til (Cc) + .title = Vis feltet Kopi til ({ ctrl-cmd-shift-pretty-prefix }{ $key }) +bcc-address-row-label = + .value = Skjult kopi til (Bcc) +# $key (String) - the shortcut key for this field +show-bcc-row-main-menuitem = + .label = Feltet Skjult kopi til (Bcc) + .accesskey = S + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } +# No acceltext should be shown. +# The label should match the show-bcc-row-button text. +show-bcc-row-extra-menuitem = + .label = Skjult kopi til (Bcc) + .accesskey = B +# $key (String) - the shortcut key for this field +show-bcc-row-button = Skjult kopi til (Bcc) + .title = Vis feltet Skjult kopi til ({ ctrl-cmd-shift-pretty-prefix }{ $key }) +extra-address-rows-menu-button = + .title = Andre adressefelter, der skal vises +# $count (Number) - the count of addresses in the "To" and "Cc" fields. +many-public-recipients-notice = + { $count -> + [one] Din meddelelse har en offentlig modtager. Du kan undgå at afsløre modtagere ved at bruge BCC i stedet + *[other] Modtagerne { $count } i Til og CC kan se hinandens adresse. Du kan undgå at afsløre modtagere ved at bruge BCC i stedet. + } many-public-recipients-bcc = .label = Brug Skjult kopi (Bcc) i stedet .accesskey = B - many-public-recipients-ignore = .label = Lad modtagerene være synlige .accesskey = L +many-public-recipients-prompt-title = For mange offentlige modtagere +many-public-recipients-prompt-cancel = Annuller afsendelse +many-public-recipients-prompt-send = Send alligevel ## Notifications # Variables: # $identity (string) - The name of the used identity, most likely an email address. compose-missing-identity-warning = Der blev ikke fundet en unik identitet, der matchede Fra-adressen. Meddelelsen bliver sendt med det aktuelle Fra-adresse og indstillinger fra identiteten { $identity }. - encrypted-bcc-warning = Når du sender en krypteret meddelelse, er modtagere i Bcc (Skjult kopi til) ikke helt skjult. Alle modtagere kan muligvis identificere dem. - encrypted-bcc-ignore-button = Forstået ## Editing @@ -200,3 +240,40 @@ compose-tool-button-remove-text-styling = .tooltiptext = Fjern tekststile + +## Filelink + + +# Placeholder file + + +# Template + +# A text used in a footer, instructing the reader where to find additional +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Læs mere om { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Læs mere om { $firstLinks } og { $lastLink }. +# Tooltip for an icon, indicating that the link is protected by a password. +cloud-file-tooltip-password-protected-link = Adgangskodebeskyttet link +cloud-file-template-size = Størrelse: +cloud-file-template-link = Link: +cloud-file-template-expiry-date = Udløbsdato: + +# Messages + +# $provider (string) - name of the online storage service that reported the error +cloud-file-connection-error-title = Forbindelsesfejl +cloud-file-connection-error = { -brand-short-name } er offline. Kunne ikke oprette forbindelse til { $provider } +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was uploaded and caused the error +cloud-file-upload-error-with-custom-message-title = Uploading af { $filename } til { $provider } mislykkedes +# $provider (string) - name of the online storage service that reported the error +cloud-file-rename-not-supported = { $provider } understøtter ikke omdøbning af filer, der allerede er uploadet. diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/messenger.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/messenger.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -2,6 +2,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +## Window controls + # Variables: # $count (Number) - Number of unread messages. unread-messages-os-tooltip = @@ -9,7 +12,6 @@ [one] 1 ulæst meddelelse *[other] { $count } ulæste meddelelser } - about-rights-notification-text = { -brand-short-name } er gratis open source-software, bygget af tusindvis af ildsjæle fra hele verden. ## Content tabs @@ -26,11 +28,9 @@ addons-and-themes-toolbarbutton = .label = Tilføjelser og temaer .tooltiptext = Håndter dine tilføjelser - quick-filter-toolbarbutton = .label = Lynfilter .tooltiptext = Filtrer meddelelser - redirect-msg-button = .label = Omdiriger .tooltiptext = Omdiriger valgte meddelelse @@ -40,10 +40,8 @@ folder-pane-toolbar = .toolbarname = Værktøjslinje for mapper .accesskey = V - folder-pane-toolbar-options-button = .tooltiptext = Indstillinger for mapperude - folder-pane-header-label = Mapper ## Folder Toolbar Header Popup @@ -51,27 +49,21 @@ folder-toolbar-hide-toolbar-toolbarbutton = .label = Skjul værktøjslinjen .accesskey = j - show-all-folders-label = .label = Alle mapper .accesskey = A - show-unread-folders-label = .label = Ulæste mapper .accesskey = U - show-favorite-folders-label = .label = Favoritmapper .accesskey = F - show-smart-folders-label = .label = Samlede mapper .accesskey = S - show-recent-folders-label = .label = Seneste mapper .accesskey = e - folder-toolbar-toggle-folder-compact-view = .label = Kompakt visning .accesskey = K @@ -81,6 +73,9 @@ redirect-msg-menuitem = .label = Omdiriger .accesskey = d +menu-file-save-as-file = + .label = Fil… + .accesskey = F ## AppMenu @@ -88,19 +83,18 @@ # and consolidated everything with Preferences. appmenu-preferences = .label = Indstillinger - +appmenu-save-as-file = + .label = Fil… +appmenu-settings = + .label = Indstillinger appmenu-addons-and-themes = .label = Tilføjelser og temaer - appmenu-help-enter-troubleshoot-mode = .label = Fejlsøgnings-tilstand… - appmenu-help-exit-troubleshoot-mode = .label = Slå fejlsøgnings-tilstand fra - appmenu-help-more-troubleshooting-info = .label = Mere teknisk information - appmenu-redirect-msg = .label = Omdiriger @@ -108,11 +102,26 @@ context-menu-redirect-msg = .label = Omdiriger +mail-context-delete-messages = + .label = + { $count -> + [one] Slet besked + *[other] Slet de valgte meddelelser + } +context-menu-decrypt-to-folder = + .label = Kopiér som dekrypteret til + .accesskey = K ## Message header pane other-action-redirect-msg = .label = Omdiriger +message-header-msg-flagged = + .title = Stjernemarkeret + .aria-label = Stjernemarkeret +message-header-msg-not-flagged = + .title = Ikke stjernemarkeret + .aria-label = Ikke stjernemarkeret ## Action Button Context Menu @@ -127,7 +136,6 @@ message-header-address-in-address-book-icon = .alt = Adresse er i din adressebogen - message-header-address-not-in-address-book-icon = .alt = Adresse er ikke i din adressebogen @@ -138,11 +146,9 @@ addon-removal-title = Fjern { $name }? addon-removal-confirmation-button = Fjern addon-removal-confirmation-message = Fjern { $name } samt dens konfiguration og data fra { -brand-short-name }? - caret-browsing-prompt-title = Caret Browsing caret-browsing-prompt-text = Ved at trykke F7 kan du slå Caret Browsing til eller fra. Denne funktion placerer en bevægelig markør på siden, hvilket giver dig mulighed for at markere tekst med tastaturet. Ønsker du at slå Caret Browsing til? caret-browsing-prompt-check-text = Spørg ikke igen. - repair-text-encoding-button = .label = Reparer tekstkodning .tooltiptext = Fastlæg den korrekte tekstkodning ud fra meddelelsens indhold @@ -152,3 +158,16 @@ no-reply-title = Svar understøttes ikke no-reply-message = Svaradressen ({ $email }) se ikke ud til at være en overvåget adresse. Meddelelser sendt til denne adresse bliver sandsynligvis ikke læst af nogen. no-reply-reply-anyway-button = Svar alligevel + +## error messages + +decrypt-and-copy-failures = { $failures } af { $total } beskeder kunne ikke dekrypteres og blev ikke kopieret. + +## Spaces toolbar + + +## Spaces toolbar pinned tab menupopup + + +## Spaces toolbar customize panel + diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/migration.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/migration.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/migration.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/migration.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -0,0 +1,15 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +migration-progress-header = Klargør { -brand-short-name }... + +## Migration tasks + + +# These strings are displayed to the user if a migration is taking a long time. +# They should be short (no more than a handful of words) and in the present tense. + +migration-task-test-fast = Tester en hurtig ændring +migration-task-test-slow = Tester en langsom ændring +migration-task-test-progress = Test af statuslinjen diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/openpgp/msgReadStatus.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/openpgp/msgReadStatus.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/openpgp/msgReadStatus.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/openpgp/msgReadStatus.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -6,7 +6,6 @@ ## Message Header Encryption Button message-header-show-security-info-key = S - # $type (String) - the shortcut key defined in the message-header-show-security-info-key message-security-button = .title = @@ -14,18 +13,16 @@ [macos] Vi meddelelsens sikkerhedsoplysninger (⌃ ⌘ { message-header-show-security-info-key }) *[other] Vi meddelelsens sikkerhedsoplysninger (Ctrl+Alt+{ message-header-show-security-info-key }) } - openpgp-view-signer-key = .label = Se underskriftsnøgle openpgp-view-your-encryption-key = .label = Se din dekrypteringsnøgle openpgp-openpgp = OpenPGP - openpgp-no-sig = Ingen digital signatur +openpgp-no-sig-info = Denne meddelelse indeholder ikke afsenderens digitale signatur. Fraværet af en digital signatur betyder, at meddelelsen kan være sendt af en anden, der udgiver sig for at have denne mailadresse. Det er også muligt at meddelelsen er blevet ændret undervejs. openpgp-uncertain-sig = Usikker digital signatur openpgp-invalid-sig = Ugyldig digital signatur openpgp-good-sig = God digital signatur - openpgp-sig-uncertain-no-key = Denne meddelelse indeholder en digital signatur, men det er usikkert, om den er korrekt. For at bekræfte signaturen, skal du få fat i en kopi af afsenderens offentlige nøgle. openpgp-sig-uncertain-uid-mismatch = Denne meddelelse indeholder en digital signatur, men der er en uoverensstemmelse. Meddelelsen er sendt fra en mailadresse, der ikke matcher underskriverens offentlige nøgle. openpgp-sig-uncertain-not-accepted = Denne meddelelse indeholder en digital signatur, men du har endnu ikke angivet, om du kan acceptere underskriverens nøgle. @@ -34,23 +31,24 @@ openpgp-sig-valid-unverified = Denne meddelelse indeholder en gyldig digital signatur fra en nøgle, som du allerede har accepteret. Du har dog endnu ikke verificeret, om nøglen rent faktisk tilhører afsenderen. openpgp-sig-valid-verified = Denne meddelelse indeholder en gyldig digital signatur fra en verificeret nøgle. openpgp-sig-valid-own-key = Denne meddelelse indeholder en gyldig digital signatur fra din personlige nøgle. - openpgp-sig-key-id = Underskrivers nøgle-id: { $key } openpgp-sig-key-id-with-subkey-id = Underskrivers nøgle-id: { $key } (Undernøgle-id: { $subkey }) - openpgp-enc-key-id = Dit dekrypteringsnøgle-id: { $key } openpgp-enc-key-with-subkey-id = Dit dekrypteringsnøgle-id: { $key } (Undernøgle-id: { $subkey }) - +openpgp-enc-none = Meddelelsen er ikke krypteret +openpgp-enc-none-label = Denne meddelelse blev ikke krypteret, inden den blev sendt. Oplysninger, der er sendt over internettet uden kryptering, kan være set af andre personer undervejs. +openpgp-enc-invalid-label = Meddelelsen kan ikke dekrypteres +openpgp-enc-invalid = Denne meddelelse blev krypteret, inden den blev sendt til dig, men den kan ikke dekrypteres. +openpgp-enc-clueless = Der er ukendte problemer med denne krypterede meddelelse. +openpgp-enc-valid-label = Meddelelsen er krypteret +openpgp-enc-valid = Denne besked blev krypteret, før den blev sendt til dig. Kryptering sikrer, at beskeden kun kan læses af de modtagere, den var beregnet til. openpgp-unknown-key-id = Ukendt nøgle - openpgp-other-enc-additional-key-ids = Derudover er meddelelsen krypteret til ejerne af følgende nøgler: openpgp-other-enc-all-key-ids = Meddelelsen er krypteret til ejerne af følgende nøgler: - openpgp-message-header-encrypted-ok-icon = .alt = Dekryptering færdig openpgp-message-header-encrypted-notok-icon = .alt = Dekryptering mislykkedes - openpgp-message-header-signed-ok-icon = .alt = God signatur # Mismatch icon is used for notok state as well diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -16,15 +16,13 @@ .label = Åbn detaljer og rediger accept… openpgp-one-recipient-status-discover = .label = Find ny eller opdateret nøgle - openpgp-one-recipient-status-instruction1 = For at sende en end to end-krypteret meddelelse til en modtager, skal du få fat i deres offentlige OpenPGP-nøgle og markere den som accepteret. openpgp-one-recipient-status-instruction2 = For at fat i deres offentlige nøgle, skal du importere den fra en mail, de har sendt til dig, og som indeholder nøglen. Alternativt kan du prøve at finde deres offentlige nøgle i et register. - openpgp-key-own = Accepteret (personlig nøgle) openpgp-key-secret-not-personal = Ikke brugbar openpgp-key-verified = Accepteret (verificeret) openpgp-key-unverified = Accepteret (ikke-verificeret) openpgp-key-undecided = Ikke accepteret (uafklaret) openpgp-key-rejected = Ikke accepteret (afvist) - +openpgp-key-expired = Udløbet openpgp-intro = Tilgængelige offentlige nøgler for { $key } diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/otr/add-finger.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/otr/add-finger.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Tilføj OTR-nøglefingeraftryk - +otr-add-finger-title = Tilføj OTR-nøglefingeraftryk # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Indtast OTR-nøglefingeraftryk for { $name }. - otr-add-finger-fingerprint = Fingeraftryk: otr-add-finger-tooltip-error = Der er indtastet et ugyldigt tegn. Kun bogstaverne ABCDEF samt tal er tilladt - otr-add-finger-input = .placeholder = Det 40 tegn lange OTR-nøglefingeraftryk diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/otr/finger.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/otr/finger.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Luk .title = Tidligere sete OTR-fingeraftryk - +otr-finger-title = Tidligere sete OTR-fingeraftryk finger-intro = OTR-nøglefingeraftryk fra tidligere end to end-krypterede samtaler. - finger-screen-name = .label = Kontakt finger-verified = .label = Bekræftelsesstatus finger-fingerprint = .label = Fingeraftryk - finger-remove = .label = Fjern valgte - finger-remove-all = .label = Fjern alle diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/otr/otrUI.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/otr/otrUI.ftl 2022-04-15 07:51:29.000000000 +0000 @@ -6,86 +6,60 @@ refresh-label = Opdater den krypterede samtale auth-label = Bekræft din kontakts identitet reauth-label = Genbekræft din kontakts identitet - auth-cancel = Annuller auth-cancel-access-key = A - auth-error = Der opstod en fejl under bekræftelsen af din kontakts identitet. auth-success = Bekræftelse af din kontakts identitet er fuldført. auth-success-them = Din kontakt har bekræftet din identitet. Det kan være en god idé også at bekræfte deres identitet ved at stille dem dit eget spørgsmål. auth-fail = Kunne ikke bekræfte din kontakts identitet. auth-waiting = Venter på, at kontakten afslutter bekræftelsen... - finger-verify = Bekræft finger-verify-access-key = B - +finger-ignore = Ignorer +finger-ignore-access-key = g # Do not translate 'OTR' (name of an encryption protocol) buddycontextmenu-label = Tilføj ORT-fingeraftryk - # Variables: # $name (String) - the screen name of a chat contact person alert-start = Forsøger at starte en krypteret samtale med { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-refresh = Forsøger at opdatere den krypterede samtale med { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-gone-insecure = Den krypterede samtale med { $name } sluttede. - # Variables: # $name (String) - the screen name of a chat contact person finger-unseen = { $name }s identitet er ikke bekræftet endnu. Tilfældig aflytning er ikke mulig, men med en vis indsats kan nogen lytte med. Bekræft denne kontakts identitet for at forhindre overvågning. - # Variables: # $name (String) - the screen name of a chat contact person finger-seen = { $name } kontakter dig fra en ukendt computer. Tilfældig aflytning er ikke mulig, men med en vis indsats kan nogen lytte med. Bekræft denne kontakts identitet for at forhindre overvågning. - state-not-private = Den aktuelle samtale er ikke privat. - state-generic-not-private = Den aktuelle samtale er ikke privat. - # Variables: # $name (String) - the screen name of a chat contact person state-unverified = Den aktuelle samtale er krypteret, men ikke privat, da { $name }s identitet endnu ikke er bekræftet. - state-generic-unverified = Den aktuelle samtale er krypteret, men ikke privat, da nogle identiteter endnu ikke er bekræftet. - # Variables: # $name (String) - the screen name of a chat contact person state-private = { $name }s identitet er verificeret. Den aktuelle samtale er krypteret og privat. - state-generic-private = Den aktuelle samtale er krypteret og privat. - # Variables: # $name (String) - the screen name of a chat contact person state-finished = { $name } har afsluttet sin krypterede samtale med dig; du bør gøre det samme. - state-not-private-label = Usikker state-unverified-label = Ubekræftet state-private-label = Privat state-finished-label = Afsluttet - # Variables: # $name (String) - the screen name of a chat contact person verify-request = { $name } anmodede om bekræftelse af din identitet. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-private = Du har bekræftet { $name }s identitet. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-unverified = { $name }s identitet er ikke bekræftet. - -verify-title = Bekræft din kontakts identitet -error-title = Fejl -success-title = End to end-kryptering -success-them-title = Bekræft din kontakts identitet -fail-title = Kunne ikke bekræfte -waiting-title = Bekræftelsesanmodning sendt - # Do not translate 'OTR' (name of an encryption protocol) # Variables: # $error (String) - contains an error message that describes the cause of the failure diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/am-im.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/am-im.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/am-im.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/am-im.ftl 2022-04-15 07:51:31.000000000 +0000 @@ -4,3 +4,13 @@ account-settings-title = Indstillinger for godkendelse account-channel-title = Standardkanaler +chat-autologin = + .label = Log på ved start +chat-encryption-generic = Generisk +chat-encryption-status = Krypteringsstatus +chat-encryption-placeholder = Kryptering ikke initialiseret. +chat-encryption-sessions = Sessioner +chat-encryption-session-verify = bekræft + .title = Bekræft denne sessions identitet +chat-encryption-session-trusted = pålidelig + .title = Denne sessions identitet er bekræftet diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/connection.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/connection.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/connection.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/connection.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -4,20 +4,16 @@ connection-dns-over-https-url-resolver = Brug udbyder .accesskey = u - # Variables: # $name (String) - Display name or URL for the DNS over HTTPS provider connection-dns-over-https-url-item-default = .label = { $name } (standard) .tooltiptext = Brug standard-URL'en til DNS-opslag over HTTPS - connection-dns-over-https-url-custom = .label = Tilpasset .accesskey = e .tooltiptext = Angiv den URL, du foretrækker til DNS-opslag over HTTPS - connection-dns-over-https-custom-label = Tilpasset - connection-dialog-window = .title = Forbindelsesindstillinger .style = @@ -25,90 +21,74 @@ [macos] width: 44em !important *[other] width: 49em !important } - connection-disable-extension = .label = Deaktiver udvidelse - +disable-extension-button = Deaktiver udvidelse +# Variables: +# $name (String) - The extension that is controlling the proxy settings. +# +# The extension-icon is the extension's icon, or a fallback image. It should be +# purely decoration for the actual extension name, with alt="". +proxy-settings-controlled-by-extension = Udvidelsen { $name } kontrollerer, hvordan { -brand-short-name } opretter forbindelse til internettet. connection-proxy-legend = Konfigurer proxy til at tilgå internettet - proxy-type-no = .label = Ingen proxy .accesskey = I - proxy-type-wpad = .label = Auto-detekter proxy-indstillinger for dette netværk .accesskey = A - proxy-type-system = .label = Brug systemets proxy-indstillinger .accesskey = r - proxy-type-manual = .label = Manuel proxy-konfiguration .accesskey = M - proxy-http-label = .value = HTTP proxy: .accesskey = h - http-port-label = .value = Port: .accesskey = p - proxy-http-sharing = .label = Brug også denne proxy til HTTPS .accesskey = x - proxy-https-label = .value = HTTPS-proxy: .accesskey = S - ssl-port-label = .value = Port: .accesskey = o - proxy-socks-label = .value = SOCKS vært: .accesskey = c - socks-port-label = .value = Port: .accesskey = t - proxy-socks4-label = .label = SOCKS v4 .accesskey = 4 - proxy-socks5-label = .label = SOCKS v5 .accesskey = 5 - proxy-type-auto = .label = Automatisk proxy-konfigurations-URL: .accesskey = U - proxy-reload-label = .label = Genindlæs .accesskey = e - no-proxy-label = .value = Ingen proxy for: .accesskey = n - no-proxy-example = Fx .mozilla.org, .net.dk, 192.168.1.0/24 - # Do not translate "localhost", "127.0.0.1/8" and "::1". (You can translate "and".) connection-proxy-noproxy-localhost-desc-2 = Forbindelser til localhost, 127.0.0.1/8 og ::1 er aldrig forbundet via en proxy. - proxy-password-prompt = .label = Spørg ikke efter godkendelse, hvis adgangskoden er gemt .accesskey = g .tooltiptext = Denne indstilling godkender dig automatisk overfor proxy-servere, når du har gemt login-informationer til dem. Du bliver spurgt, hvis godkendelsen slår fejl. - proxy-remote-dns = .label = Proxy-DNS ved brug af SOCKS v5 .accesskey = D - proxy-enable-doh = .label = Aktiver DNS via HTTPS .accesskey = k diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/dock-options.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/dock-options.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/dock-options.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/dock-options.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -5,22 +5,20 @@ dock-options-window-dialog = .title = Indstillinger for app-ikon .style = width: 35em; - +dock-options-show-badge = + .label = Vis badge-ikon + .accesskey = V bounce-system-dock-icon = .label = Animer app-ikonet når en ny meddelelse modtages .accesskey = A - dock-icon-legend = App-ikon-mærke - dock-icon-show-label = .value = Mærk app-ikonet med: - count-unread-messages-radio = .label = Antal ulæste meddelelser .accesskey = u - count-new-messages-radio = .label = Antal meddelelser .accesskey = n - notification-settings-info = Du kan deaktivere mærket på meddelelsessiden i systemindstillingerne. +notification-settings-info2 = Du kan deaktivere emblemet i meddelelsesruden i Systemindstillinger. diff -Nru thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/da/mail/messenger/preferences/preferences.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/mail/messenger/preferences/preferences.ftl 2022-04-15 07:51:31.000000000 +0000 @@ -4,126 +4,83 @@ close-button = .aria-label = Luk - preferences-doc-title = Indstillinger - +preferences-doc-title2 = Indstillinger category-list = .aria-label = Kategorier - pane-general-title = Generelt category-general = .tooltiptext = { pane-general-title } - pane-compose-title = Redigering category-compose = .tooltiptext = Redigering - pane-privacy-title = Privatliv & sikkerhed category-privacy = .tooltiptext = Privatliv & sikkerhed - pane-chat-title = Chat category-chat = .tooltiptext = Chat - pane-calendar-title = Kalender category-calendar = .tooltiptext = Kalender - general-language-and-appearance-header = Sprog og udseende - general-incoming-mail-header = Indgående meddelelser - general-files-and-attachment-header = Filer og vedhæftninger - general-tags-header = Mærker - general-reading-and-display-header = Læsning & visning - general-updates-header = Opdateringer - general-network-and-diskspace-header = Netværk & diskplads - general-indexing-label = Indeksering - composition-category-header = Skrivning - composition-attachments-header = Vedhæftede filer - composition-spelling-title = Stavning - compose-html-style-title = HTML-stil - composition-addressing-header = Adresser - privacy-main-header = Privatliv - privacy-passwords-header = Adgangskoder - privacy-junk-header = Spam - collection-header = Indsamling og brug af data i { -brand-short-name } - collection-description = Vi stræber efter at give dig mulighed for selv at vælge og indsamler kun, hvad vi har brug for til at forbedre { -brand-short-name } for alle. Vi spørger altid om din tilladelse, før vi modtager personlig information. collection-privacy-notice = Privatlivspolitik - collection-health-report-telemetry-disabled = Du tillader ikke længere, at { -vendor-short-name } indsamler teknisk data og data om brug. Alle tidligere data vil blive slettet indenfor 30 dage. collection-health-report-telemetry-disabled-link = Læs mere - collection-health-report = .label = Tillad at { -brand-short-name } indsender tekniske data og data om brug til { -vendor-short-name } .accesskey = i collection-health-report-link = Læs mere - # This message is displayed above disabled data sharing options in developer builds # or builds with no Telemetry support available. collection-health-report-disabled = Data-rapportering er deaktiveret for denne build-konfiguration - collection-backlogged-crash-reports = .label = Tillad at { -brand-short-name } sender ophobede fejlrapporter på dine vegne .accesskey = f collection-backlogged-crash-reports-link = Læs mere - privacy-security-header = Sikkerhed - privacy-scam-detection-title = Svindelmails - privacy-anti-virus-title = Antivirus - privacy-certificates-title = Certifikater - chat-pane-header = Chat - chat-status-title = Status - chat-notifications-title = Beskeder - chat-pane-styling-header = Stil - choose-messenger-language-description = Vælg det sprog, der skal bruges i brugerfladen i { -brand-short-name }. manage-messenger-languages-button = .label = Vælg alternativer… .accesskey = l confirm-messenger-language-change-description = Genstart { -brand-short-name } for at anvende ændringerne confirm-messenger-language-change-button = Anvend og genstart - update-setting-write-failure-title = Kunne ikke gemme indstillinger for opdatering - # Variables: # $path (String) - Path to the configuration file # The newlines between the main text and the line containing the path is # intentional so the path is easier to identify. update-setting-write-failure-message = { -brand-short-name } stødte på en fejl og gemte ikke ændringen. Bemærk, at for at kunne gemme ændringer, skal der være tilladelse til at skrive til den nedennævnte fil. Du eller en systemadministrator kan måske løse problemet ved at give gruppen Users fuld kontrol over filen. - update-in-progress-title = Opdaterer… - update-in-progress-message = Skal { -brand-short-name } fortsætte med denne opdatering? - update-in-progress-ok-button = &Annuller # Continue is the cancel button so pressing escape or using a platform standard # method of closing the UI will not discard the update. update-in-progress-cancel-button = &Fortsæt - account-button = Kontoindstillinger open-addons-sidebar-button = Tilføjelser og temaer @@ -131,13 +88,11 @@ # This message can be seen by trying to add a Primary Password. primary-password-os-auth-dialog-message-win = For at oprette en hovedadgangskode skal du indtaste dine login-oplysninger til Windows. Dette hjælper dig med at holde dine konti sikre. - # This message can be seen by trying to add a Primary Password. # The macOS strings are preceded by the operating system with "Thunderbird is trying to " # and includes subtitle of "Enter password for the user "xxx" to allow this." These # notes are only valid for English. Please test in your locale. primary-password-os-auth-dialog-message-macosx = oprette en hovedadgangskode - # Don't change this label. master-password-os-auth-dialog-caption = { -brand-full-name } @@ -147,32 +102,29 @@ .key = f focus-search-shortcut-alt = .key = k - general-legend = { -brand-short-name } startside - start-page-label = .label = Vis startsiden i meddelelsesområdet, når { -brand-short-name } starter .accesskey = V - location-label = .value = Startside: .accesskey = S restore-default-label = .label = Gendan standard .accesskey = G - default-search-engine = Standardsøgetjeneste -add-search-engine = - .label = Tilføj fra fil - .accesskey = F +add-web-search-engine = + .label = Tilføj… + .accesskey = T remove-search-engine = .label = Fjern .accesskey = r - +add-opensearch-provider-title = Tilføj OpenSearch-udbyder +adding-opensearch-provider-failed-title = Tilføjelse af OpenSearch-udbyder mislykkedes +adding-opensearch-provider-failed-text = Kunne ikke tilføje OpenSearch Provider for { $url }. minimize-to-tray-label = .label = Flyt { -brand-short-name } til systembakken, når programmet minimeres .accesskey = m - new-message-arrival = Når der kommer nye meddelelser: mail-play-sound-label = .label = @@ -188,30 +140,24 @@ mail-play-button = .label = Afspil .accesskey = A - change-dock-icon = Skift indstillinger for app-ikon app-icon-options = .label = Indstillinger for app-ikon… .accesskey = I - notification-settings = Meddelelser og standardlyden kan deaktiveres på meddelelsessiden i systemindstillingerne. - +notification-settings2 = Meddelelser og standardlyden kan deaktiveres på meddelelsessiden i systemindstillingerne. animated-alert-label = .label = Vis en pop op-meddelelse .accesskey = p customize-alert-label = .label = Tilpas… .accesskey = T - biff-use-system-alert = .label = Brug systemmeddelelse - tray-icon-unread-label = .label = Vis ikon i systembakken for ulæste meddelelser .accesskey = k - tray-icon-unread-description = Anbefales, når du bruges små knapper på proceslinjen - mail-system-sound-label = .label = Standard systemlyd ved modtagelse af ny mail .accesskey = y @@ -221,27 +167,21 @@ mail-browse-sound-button = .label = Gennemse… .accesskey = e - enable-gloda-search-label = .label = Aktiver global søgning og indeksering .accesskey = A - datetime-formatting-legend = Dato- og tidsformat language-selector-legend = Sprog - allow-hw-accel = .label = Brug hardware-acceleration hvor muligt .accesskey = h - store-type-label = .value = Lagertype for meddelelser for nye konti: .accesskey = L - mbox-store-label = .label = En fil pr. mappe (mbox) maildir-store-label = .label = En fil pr. meddelelse (maildir) - scrolling-legend = Scrolling autoscroll-label = .label = Brug autoscrolling @@ -249,7 +189,6 @@ smooth-scrolling-label = .label = Brug blød scrolling .accesskey = r - system-integration-legend = Systemintegration always-check-default = .label = Undersøg altid om { -brand-short-name } er standardmailprogrammet, når det startes @@ -257,7 +196,6 @@ check-default-button = .label = Undersøg nu… .accesskey = n - # Note: This is the search engine name for all the different platforms. # Platforms that don't support it should be left blank. search-engine-name = @@ -266,26 +204,20 @@ [windows] Windows Søgning *[other] { "" } } - search-integration-label = .label = Tillad { search-engine-name } at søge efter meddelelser .accesskey = T - config-editor-button = .label = Avancerede indstillinger… .accesskey = r - return-receipts-description = Vælg hvordan { -brand-short-name } skal håndtere kvitteringer return-receipts-button = .label = Kvitteringer… .accesskey = v - update-app-legend = { -brand-short-name }-opdateringer - # Variables: # $version (String): version of Thunderbird, e.g. 68.0.1 update-app-version = Version { $version } - allow-description = Giv { -brand-short-name } tilladelse til at automatic-updates-label = .label = Installere opdateringer automatisk (anbefalet, forbedrer sikkerheden) @@ -293,40 +225,30 @@ check-updates-label = .label = Søge efter opdateringer, men lade mig vælge om de skal installeres .accesskey = ø - update-history-button = .label = Vis opdateringshistorik .accesskey = V - use-service = .label = Brug en baggrundsservice til at installere opdateringer .accesskey = b - cross-user-udpate-warning = Denne indstilling gælder for alle Windows-konti og { -brand-short-name }-profiler der bruger denne installation af { -brand-short-name }. - networking-legend = Forbindelse proxy-config-description = Konfigurer hvordan { -brand-short-name } forbinder til internettet - network-settings-button = .label = Indstillinger… .accesskey = I - offline-legend = Offline offline-settings = Rediger offline-indstillinger - offline-settings-button = .label = Offline… .accesskey = O - diskspace-legend = Diskplads offline-compact-folder = .label = Optimer mapper, når det kan spare mere end .accesskey = k - offline-compact-folder-automatically = .label = Spørg hver gang inden der optimeres .accesskey = S - compact-folder-size = .value = MB @@ -337,7 +259,6 @@ use-cache-before = .value = Benyt op til .accesskey = B - use-cache-after = MB til mellemlageret ## @@ -345,42 +266,31 @@ smart-cache-label = .label = Tilsidesæt automatisk cachehåndtering .accesskey = s - clear-cache-button = .label = Ryd nu .accesskey = R - fonts-legend = Skrifttyper & farver - default-font-label = .value = Standardskrifttype: .accesskey = S - default-size-label = .value = Størrelse: .accesskey = ø - font-options-button = .label = Avanceret… .accesskey = A - color-options-button = .label = Farver… .accesskey = F - display-width-legend = Meddelelser i ren tekst - # Note : convert-emoticons-label 'Emoticons' are also known as 'Smileys', e.g. :-) convert-emoticons-label = .label = Vis smiley-ansigter som grafik. .accesskey = V - display-text-label = Ved visning af citerede meddelelser i ren tekst-format: - style-label = .value = Stil: .accesskey = i - regular-style-item = .label = Normal bold-style-item = @@ -389,37 +299,25 @@ .label = Kursiv bold-italic-style-item = .label = Fed kursiv - size-label = .value = Størrelse: .accesskey = r - regular-size-item = .label = Normal bigger-size-item = .label = Større smaller-size-item = .label = Mindre - quoted-text-color = .label = Farve: .accesskey = e - search-handler-table = .placeholder = Filtrer indholdstyper og handlinger - -type-column-label = - .label = Indholdstype - .accesskey = I - -action-column-label = - .label = Handling - .accesskey = H - +type-column-header = Indholdstype +action-column-header = Handling save-to-label = .label = Gem filer i .accesskey = f - choose-folder-label = .label = { PLATFORM() -> @@ -431,30 +329,22 @@ [macos] G *[other] G } - always-ask-label = .label = Spørg mig altid, hvor filer skal gemmes .accesskey = S - - display-tags-text = Mærkater kan bruges til at kategorisere og prioritere dine meddelelser - new-tag-button = .label = Nyt… .accesskey = N - edit-tag-button = .label = Rediger… .accesskey = R - delete-tag-button = .label = Slet .accesskey = S - auto-mark-as-read = .label = Marker automatisk som læst .accesskey = M - mark-read-no-delay = .label = Marker omgående .accesskey = a @@ -465,33 +355,26 @@ mark-read-delay = .label = Efter visning i .accesskey = v - seconds-label = sekunder ## open-msg-label = .value = Åbn meddelelse i: - open-msg-tab = .label = Et nyt faneblad .accesskey = f - open-msg-window = .label = Et nyt meddelelsesvindue .accesskey = n - open-msg-ex-window = .label = Et eksisterende meddelelsesvindue .accesskey = e - close-move-delete = .label = Luk meddelelsesvinduet/-fanen ved flytning eller sletning .accesskey = L - display-name-label = .value = Vist navn: - condensed-addresses-label = .label = Vis kun "Vis som"-feltet for personer i min adressebog .accesskey = p @@ -501,13 +384,10 @@ forward-label = .value = Videresend meddelelser som: .accesskey = v - inline-label = .label = En del af selve meddelelsen - as-attachment-label = .label = Vedhæftet fil - extension-label = .label = tilføj filendelse til filnavn .accesskey = t @@ -518,7 +398,6 @@ auto-save-label = .label = Gem automatisk hvert .accesskey = m - auto-save-end = minut ## @@ -526,248 +405,182 @@ warn-on-send-accel-key = .label = Bekræft når genvejstaster bruges til at sende meddelelser .accesskey = æ - spellcheck-label = .label = Udfør stavekontrol før meddelelsen sendes .accesskey = U - spellcheck-inline-label = .label = Anvend løbende stavekontrol .accesskey = n - language-popup-label = .value = Sprog: .accesskey = S - download-dictionaries-link = Hent flere ordbøger - font-label = .value = Skrifttype: .accesskey = S - font-size-label = .value = Størrelse: .accesskey = ø - default-colors-label = .label = Brug læserens standardfarver .accesskey = u - font-color-label = .value = Tekstfarve: .accesskey = F - bg-color-label = .value = Baggrundsfarve: .accesskey = B - restore-html-label = .label = Gendan standard .accesskey = G - default-format-label = .label = Benyt afsnitsformat som standard i stedet for formatet for almindelig tekst .accesskey = e - format-description = Konfigurering af meddelelsesindholdet: - send-options-label = .label = Afsendelsesindstillinger… .accesskey = A - autocomplete-description = Søg efter adresser i: - ab-label = .label = Lokale adressebøger .accesskey = L - directories-label = .label = LDAP-server: .accesskey = s - directories-none-label = .none = Ingen - edit-directories-label = .label = Rediger LDAP-servere… .accesskey = R - email-picker-label = .label = Tilføj automatisk modtageres mailadresser i: .accesskey = A - default-directory-label = .value = Standardmappe ved start i vinduet Adressebog: .accesskey = t - default-last-label = .none = Senest brugte mappe - attachment-label = .label = Kontroller for manglende vedhæftede filer .accesskey = K - attachment-options-label = .label = Stikord… .accesskey = i - enable-cloud-share = .label = Tilbyd at bruge Filelink ved filer større end cloud-share-size = .value = MB - add-cloud-account = .label = Tilføj… .accesskey = T .defaultlabel = Tilføj… - remove-cloud-account = .label = Fjern .accesskey = F - find-cloud-providers = .value = Find flere udbydere… - cloud-account-description = Tilføj en ny Filelink-tjeneste ## Privacy Tab mail-content = Meddelelsesindhold - remote-content-label = .label = Tillad eksternt indhold i meddelelser .accesskey = T - exceptions-button = .label = Undtagelser… .accesskey = n - remote-content-info = .value = Læs mere om problemer med privatliv i forbindelse med eksternt indhold - web-content = Webindhold - history-label = .label = Husk websteder og links jeg har besøgt .accesskey = H - cookies-label = .label = Accepter cookies fra websteder .accesskey = A - third-party-label = .value = Accepter tredjeparts cookies: .accesskey = c - third-party-always = .label = Altid third-party-never = .label = Aldrig third-party-visited = .label = Fra besøgte - keep-label = .value = Behold indtil: .accesskey = B - keep-expire = .label = De udløber keep-close = .label = Jeg lukker { -brand-short-name } keep-ask = .label = Spørg mig hver gang - cookies-button = .label = Vis cookies… .accesskey = V - do-not-track-label = .label = Send et “Spor mig ikke”-signal til websider som tegn på, at du ikke ønsker at blive sporet .accesskey = n - learn-button = .label = Læs mere - passwords-description = { -brand-short-name } kan huske adgangskoder til alle dine konti, så du ikke behøver at indtaste dem. - passwords-button = .label = Gemte adgangskoder… .accesskey = G - primary-password-description = Hovedadgangskoden beskytter alle dine adgangskoder, men du skal indtaste den ved hver opstart. - primary-password-label = .label = Brug hovedadgangskode .accesskey = u - primary-password-button = .label = Skift hovedadgangskode… .accesskey = S - forms-primary-pw-fips-title = Du er i FIPS-tilstand. FIPS kræver at hovedadgangskoden er sat. forms-master-pw-fips-desc = Ændring af adgangskode mislykkedes - - junk-description = Du kan redigere kontospecifikke spam-indstillinger i vinduet Kontoindstillinger. - junk-label = .label = Når du markerer meddelelsen som spam: .accesskey = å - junk-move-label = .label = Flyt dem til mappen Spam på kontoen .accesskey = F - junk-delete-label = .label = Slet dem .accesskey = S - junk-read-label = .label = Marker spam-meddelelser som læste .accesskey = M - junk-log-label = .label = Aktiver logning af spam-filter .accesskey = A - junk-log-button = .label = Vis log .accesskey = V - reset-junk-button = .label = Nulstil indlærte data .accesskey = N - phishing-description = { -brand-short-name } kan analysere meddelelser for mailsvindel ved at se efter standardteknikker, som benyttes til at snyde dig. - phishing-label = .label = Fortæl mig, hvis meddelelsen jeg læser er mailsvindel .accesskey = F - antivirus-description = { -brand-short-name } kan gøre det lettere for antivirusprogrammer at analysere indkommende meddelelser for virus, før de gemmes lokalt. - antivirus-label = .label = Tillad antivirusprogrammer at sætte indkommende meddelelser i karantæne .accesskey = T - certificate-description = Når en server forespørger mit personlige certifikat: - certificate-auto = .label = Vælg et automatisk .accesskey = a - certificate-ask = .label = Spørg mig hver gang .accesskey = ø - ocsp-label = .label = Send forespørgsel til OCSP responder-servere for at bekræfte certifikaters aktuelle gyldighed .accesskey = e - certificate-button = .label = Håndter certifikater… .accesskey = H - security-devices-button = .label = Sikkerhedsenheder… .accesskey = E @@ -777,10 +590,8 @@ startup-label = .value = Når { -brand-short-name } startes: .accesskey = s - offline-label = .label = Lad mine chat-konti være offline - auto-connect-label = .label = Forbind automatisk mine chat-konti @@ -793,7 +604,6 @@ idle-label = .label = Skift min status til Ikke til stede efter .accesskey = i - idle-time-label = minutter uden aktivitet ## @@ -801,24 +611,19 @@ away-message-label = .label = og vis denne meddelelse: .accesskey = m - send-typing-label = .label = Vis, når der skrives i samtaler .accesskey = n - notification-label = Når meddelelser til dig ankommer: - show-notification-label = .label = Vis en besked .accesskey = V - notification-all = .label = med afsenderens navn og en forhåndsvisning af indholdet notification-name = .label = med afsenderens navn og intet andet notification-empty = .label = uden info fra mailen - notification-type-label = .label = { PLATFORM() -> @@ -830,31 +635,24 @@ [macos] o *[other] k } - chat-play-sound-label = .label = Afspil lyd .accesskey = l - chat-play-button = .label = Afspil .accesskey = A - chat-system-sound-label = .label = Standard systemlyd ved modtagelse af ny mail .accesskey = y - chat-custom-sound-label = .label = Brug denne lydfil .accesskey = B - chat-browse-sound-button = .label = Gennemse… .accesskey = G - theme-label = .value = Tema: .accesskey = T - style-thunderbird = .label = Thunderbird style-bubbles = @@ -865,15 +663,12 @@ .label = Papirark style-simple = .label = Simpel - preview-label = Forhåndsvisning: no-preview-label = Ingen forhåndsvisning no-preview-description = Temaet er ikke gyldigt eller kan ikke vises lige nu (tilføjelse deaktiveret, fejlsikret tilstand ...). - chat-variant-label = .value = Variant: .accesskey = V - # This is used to determine the width of the search field in about:preferences, # in order to make the entire placeholder string visible # @@ -888,13 +683,25 @@ ## Preferences UI Search Results -search-results-header = Søgeresultater +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input2 = + .style = width: 15.4em + .placeholder = Søg i indstillinger +## Settings UI Search Results + +search-results-header = Søgeresultater # `` will be replaced by the search term. search-results-empty-message = { PLATFORM() -> [windows] Beklager! Der er ingen resultater for "" i Indstillingerne. *[other] Beklager! Der er ingen resultater for "" i Indstillingerne. } - search-results-help-link = Har du brug for hjælp? Besøg Hjælp til { -brand-short-name } diff -Nru thunderbird-91.7.0+build2/l10n/da/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/da/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/da/netwerk/necko.properties 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/netwerk/necko.properties 2022-04-15 07:51:30.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Cookien "%1$S" er blevet afvist, fordi den allerede er udløbet. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Cookien "%1$S" er blevet afvist, fordi den er i en cross-site-kontekst og dens "SameSite" er "Lax" eller "Strict". + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Advarsel: '%1$S' er forældet, brug '%2$S' i stedet diff -Nru thunderbird-91.7.0+build2/l10n/da/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/da/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/da/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:51:30.000000000 +0000 @@ -19,7 +19,7 @@ # example: `3 minutes` aboutReader.estimatedReadTimeValue1=#1 minut;#1 minutter -#LOCALIZATION NOTE (aboutReader.estimatedReadingTimeRange1): Semi-colon list of plural forms. +#LOCALIZATION NOTE (aboutReader.estimatedReadTimeRange1): Semi-colon list of plural forms. # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # When there is some uncertainty in how long the article will take to read show a range of # minutes it is expected to take. @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Luk læsevisning @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Lyst farveskema aboutReader.toolbar.colorschemedark = Mørkt farveskema aboutReader.toolbar.colorschemesepia = Sepia farveskema +aboutReader.toolbar.colorschemeauto = Automatisk farveskema diff -Nru thunderbird-91.7.0+build2/l10n/da/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/da/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/da/toolkit/chrome/global/narrate.properties 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/toolkit/chrome/global/narrate.properties 2022-04-15 07:51:29.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Lyt back = Tilbage start = Start stop = Stop +# %S is the keyboard shortcut for the start command +start-label = Start (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Stop (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = S forward = Frem speed = Hastighed selectvoicelabel = Stemme: diff -Nru thunderbird-91.7.0+build2/l10n/da/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/da/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/da/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:36:42.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } frame + *[other] { $frames } frames + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } kanal + *[other] { $channels } kanaler + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/da/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/da/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/da/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -9,11 +9,6 @@ experimental-features-css-masonry-description = Aktiverer den eksperimentelle funktion med CSS Masonry-layout. Læs denne artikel for at få et overblik over funktionen. Hvis du har feedback, så skriv gerne en kommentar på dette issue på GitHub eller på denne bug. # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. -experimental-features-css-cascade-layers = - .label = CSS: Cascade Layers -experimental-features-css-cascade-layers-description = Aktiverer understørrelse af CSS Cascade Layers. Se flere detaljer i den foreløbige specifikation. Rapportér gerne fejl med denne funktionalitet på bug 1699215. -# The title of the experiment should be kept in English as it may be referenced -# by various online articles and is technical in nature. experimental-features-web-gpu2 = .label = Web API: WebGPU experimental-features-web-gpu-description2 = Denne nye API giver low-level understøttelse til at anvende grafikprocessoren (GPU) i brugerens enhed eller computer til at lave beregninger eller rendere grafik. Specifikationen er stadig ved at blive udarbejdet . Se flere detaljer på bug 1602129. @@ -94,3 +89,7 @@ experimental-features-ime-search = .label = Adressefelt: Vis resulter under IME-komponering experimental-features-ime-search-description = En IME (Input Method Editor) er et værktøj, der lader dig indtaste komplekse symboler med et almindeligt tastatur, fx symboler fra øst-asiatiske og indiske skriftsprog. Ved aktivering af dette eksperiment holdes adressefeltet åbent med søgeresultater og forslag, når du bruger IME til at indtaste tekst. Bemærk, at IME kan vise et panel, der dækker for resultaterne i adressefeltet. Derfor foreslås denne indstilling kun for IME, der ikke anvender denne type af panel. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name }100 User-Agent-streng +experimental-features-firefox-100-description = Gør at { -brand-short-name } sender websteder en User-Agent-streng, der præsenterer browseren som { -brand-product-name } version 100. Brug denne indstilling til at teste, om websteder vil fejle, når { -brand-short-name } når et versionsnummer med tre cifre. Den rigtige { -brand-product-name } 100 lanceres efter planen i maj 2022, så test dine websteder nu. diff -Nru thunderbird-91.7.0+build2/l10n/da/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/da/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/da/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:36:43.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/da/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:51:30.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socket # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Sandboxed IPC Actor ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/de/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/de/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/de/devtools/client/aboutdebugging.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/devtools/client/aboutdebugging.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Debugging - Konfiguration - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Debugging - Umgebung / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Dieser { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Konfiguration - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB aktiviert - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB deaktiviert - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Verbunden # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Getrennt - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = Keine Geräte gefunden - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Verbinden - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Verbindung wird hergestellt… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Verbindung fehlgeschlagen - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = Verbindung nicht bestätigt, überprüfen Sie den Zielbrowser auf Mitteilungen. - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = Zeitüberschreitung beim Verbindungsaufbau - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Warten auf Browser… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Vom Computer getrennt - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Debugging-Hilfe - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Hilfe-Symbol - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Geräteliste aktualisieren @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Konfiguration - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Wählen Sie die Verbindungsmethode für das externe Debugging des Geräts. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = { about-debugging-this-firefox-runtime-name } verwenden, um Erweiterungen und Service-Worker mit dieser Version von { -brand-shorter-name } zu untersuchen. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Gerät verbinden - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Das Aktivieren dieser Einstellung wird die benötigten Komponenten für das Debuggen von Android über USB in { -brand-shorter-name } herunterladen und installieren. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = USB-Geräte aktivieren - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = USB-Geräte deaktivieren - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Wird aktualisiert… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Aktiviert about-debugging-setup-usb-status-disabled = Deaktiviert about-debugging-setup-usb-status-updating = Wird aktualisiert… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Das "Entwicklermenü" in Android aktivieren. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = USB-Debugging in Androids Menü "Entwicklermenü" aktivieren. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = USB-Debugging in Firefox auf dem Android-Gerät aktivieren. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Das Android-Gerät mit dem Computer verbinden. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Probleme mit der Verbindung mit dem USB-Gerät? Anleitung zur Fehlerbehebung - # Network section of the Setup page about-debugging-setup-network = .title = Netzwerk-Adresse - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Probleme mit der Verbindung mit der Netzwerk-Adresse? Anleitung zur Fehlerbehebung - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Hinzufügen - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = Es wurden noch keine Netzwerk-Adressen hinzugefügt. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Host - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Entfernen - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Ungültiger Host "{ $host-value }". Das erwartete Format ist "hostname:portnummer". - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Prozesse - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Leistung analysieren - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Ihre Browser-Einstellungen sind inkompatibel mit Service-Workern. Weitere Informationen - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = Der verbundene Browser verwendet eine alte Version ({ $runtimeVersion }). Die niedrigste unterstützte Version ist ({ $minVersion }). Daher handelt es sich um eine nicht unterstützte Kombination und die Entwicklerwerkzeuge funktionieren eventuell nicht. Bitte aktualisieren Sie den verbundenen Browser. Informationen zur Fehlerbehebung - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = Diese Firefox-Version kann Firefox für Android (68) nicht debuggen. Es wird empfohlen, Firefox für Android Nightly zum Testen auf dem Telefon zu installieren. Weitere Informationen - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = Der verbundene Browser ist aktueller ({ $runtimeVersion }, BuildID { $runtimeID }) als Ihr { -brand-shorter-name } ({ $localVersion }, BuildID { $localID }). Das ist eine nicht unterstützte Kombination und die Entwicklerwerkzeuge funktionieren eventuell nicht. Bitte aktualisieren Sie Firefox. Informationen zur Fehlerbehebung - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Trennen - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Verbindungsbestätigung aktivieren - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Verbindungsbestätigung deaktivieren - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Laufzeitanalyse - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Noch nichts - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Untersuchen - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Temporäres Add-on laden… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = Während der temporären Installation des Add-ons trat ein Fehler auf. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Neu laden - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Entfernen - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Hintergrundskript beenden # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = manifest.json-Datei oder .xpi/.zip-Archiv auswählen - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Diese WebExtension hat eine temporäre ID. Weitere Informationen - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = Manifest-Adresse - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = Interne UUID - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Speicherort - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = Erweiterungs-ID - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Hintergrundskript +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Wird ausgeführt +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Angehalten # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push .disabledTitle = Push für Service-Worker ist derzeit deaktiviert, falls { -brand-shorter-name } mit mehr als einem Prozess ausgeführt wird. - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Starten .disabledTitle = Das Starten von Service-Workern ist derzeit deaktiviert, falls { -brand-shorter-name } mit mehr als einem Prozess ausgeführt wird. - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Abmelden - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Wartet auf Fetch-Ereignisse - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = Wartet nicht auf Fetch-Ereignisse - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Wird ausgeführt - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Angehalten - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Wird registriert - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Geltungsbereich - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Push-Dienst - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = Das Untersuchen von Service-Workern ist derzeit deaktiviert, falls { -brand-shorter-name } mit mehr als einem Prozess ausgeführt wird. - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Tab ist nicht vollständig geladen und kann nicht untersucht werden - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Hauptprozess - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Hauptprozess des Zielbrowsers - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Werkzeuge für mehrere Prozesse - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Hauptprozess und Inhaltsprozesse des Zielbrowsers - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Nachricht schließen - # Label text used for the error details of message component. about-debugging-message-details-label-error = Fehlerdetails - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Warnungsdetails - # Label text used for default state of details of message component. about-debugging-message-details-label = Details diff -Nru thunderbird-91.7.0+build2/l10n/de/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/de/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/de/devtools/client/compatibility.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/devtools/client/compatibility.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (experimentell) compatibility-issue-prefixneeded = (Präfix erforderlich) compatibility-issue-deprecated-experimental = (veraltet, experimentell) - compatibility-issue-deprecated-prefixneeded = (veraltet, Präfix erforderlich) compatibility-issue-experimental-prefixneeded = (experimentell, Präfix erforderlich) compatibility-issue-deprecated-experimental-prefixneeded = (veraltet, experimentell, Präfix erforderlich) @@ -43,7 +42,14 @@ [one] { $number } Vorkommen *[other] { $number } Vorkommen } - compatibility-no-issues-found = Keine Kompatibilitätsprobleme gefunden. compatibility-close-settings-button = .title = Einstellungen schließen +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Kompatibilitätsprobleme in: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/de/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/de/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/de/devtools/client/debugger.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/devtools/client/debugger.properties 2022-04-15 07:51:37.000000000 +0000 @@ -642,6 +642,16 @@ ignoreContextItem.unignore=Ignorierung der Quelle beenden ignoreContextItem.unignore.accesskey=b +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Zeile ignorieren +ignoreContextItem.ignoreLine.accesskey=g + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Ignorierung der Zeile beenden +ignoreContextItem.unignoreLine.accesskey=g + # LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated # with the ignore lines context menu item ignoreContextItem.ignoreLines=Zeilen ignorieren diff -Nru thunderbird-91.7.0+build2/l10n/de/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/de/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/de/devtools/client/netmonitor.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/devtools/client/netmonitor.properties 2022-04-15 07:51:39.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → Callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=Die Zeichenkette "%S" wurde vom Anfang des unten gezeigten JSON entfernt + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Anfragetext: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL-Parameter + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Request-Header: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Kopfzeilen + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=Name + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=Wert + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Inhalt + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=Anfrageinhalt + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Request-Body: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Abbrechen +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Leeren + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Eintrag entfernen + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Zurück diff -Nru thunderbird-91.7.0+build2/l10n/de/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/de/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/de/devtools/client/toolbox.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/devtools/client/toolbox.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Popups nicht automatisch ausblenden +toolbox-meatball-menu-pseudo-locale-accented = "accented"-Sprache aktivieren +toolbox-meatball-menu-pseudo-locale-bidi = "bidi"-Sprache aktivieren ## diff -Nru thunderbird-91.7.0+build2/l10n/de/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/de/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/de/devtools/client/toolbox-options.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/devtools/client/toolbox-options.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Externes Debugging aktivieren options-enable-remote-tooltip2 = .title = Das Aktivieren dieser Einstellung ermöglicht das externe Debuggen dieser Browser-Instanz außerhalb des Programms, ggf. auf einem anderen Gerät. +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Benutzerdefinierte Formatierungen aktivieren +options-enable-custom-formatters-tooltip = + .title = Bei Aktivierung können Websites benutzerdefinierte Formatierer für DOM-Objekte definieren. # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Service-Worker über HTTP aktivieren (bei geöffneten Entwicklerwerkzeugen) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/de/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/de/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/de/devtools/client/webconsole.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/devtools/client/webconsole.properties 2022-04-15 07:51:39.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=Datei +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Alle Nachrichten kopieren +webconsole.menu.copyAllMessages.accesskey=N + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Alle Nachrichten in Datei speichern +webconsole.menu.saveAllMessagesFile.accesskey=D + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/de/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/de/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/de/dom/chrome/dom/dom.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/dom/chrome/dom/dom.properties 2022-04-15 07:51:39.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Bitte geben Sie eine Internetadresse ein. FormValidationInvalidDate=Bitte geben Sie ein gültiges Datum ein. FormValidationInvalidTime=Bitte geben Sie eine gültige Uhrzeit ein. +FormValidationInvalidDateTime=Bitte geben Sie ein gültiges Datum und eine gültige Uhrzeit ein. +FormValidationInvalidDateMonth=Bitte geben Sie einen gültigen Monat ein. +FormValidationInvalidDateWeek=Bitte geben Sie eine gültige Woche ein. FormValidationPatternMismatch=Bitte halten Sie sich an das vorgegebene Format. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Bitte halten Sie sich an das vorgegebene Format: %S. @@ -432,6 +435,6 @@ OffscreenCanvasToBlobWarning=OffscreenCanvas.toBlob() ist veraltet. Verwenden Sie stattdessen OffscreenCanvas.convertToBlob(). # LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" -IDBDatabaseCreateMutableFileWarning=IDBDatabase.createMutableFile() sollte nicht mehr verwendet werden. Wenn diese API standardisiert wird, wird dies wahrscheinlich unter der Bestrebung "Origin Private File System" unter https://bugzil.la/1748667 passieren. +IDBDatabaseCreateMutableFileWarning=IDBDatabase.createMutableFile() sollte nicht mehr verwendet werden. Falls diese API standardisiert wird, dann erfolgt dies wahrscheinlich unter der Bestrebung "Origin Private File System" unter https://bugzil.la/1748667 . # LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" -IDBMutableFileOpenWarning=IDBMutableFile.open() sollte nicht mehr verwendet werden. Wenn diese API standardisiert wird, wird dies wahrscheinlich unter der Bestrebung "Origin Private File System" unter https://bugzil.la/1748667 passieren. +IDBMutableFileOpenWarning=IDBMutableFile.open() sollte nicht mehr verwendet werden. Falls diese API standardisiert wird, dann erfolgt dies wahrscheinlich unter der Bestrebung "Origin Private File System" unter https://bugzil.la/1748667 diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/browser/appExtensionFields.ftl thunderbird-91.8.1+build1/l10n/de/mail/browser/appExtensionFields.ftl --- thunderbird-91.7.0+build2/l10n/de/mail/browser/appExtensionFields.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/browser/appExtensionFields.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -2,6 +2,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +## Theme names and descriptions used in the Themes panel in about:addons + +# "Auto" is short for automatic. It can be localized without limitations. +extension-default-theme-name-auto=System-Theme – automatisch +extension-default-theme-description=Dem Theme des Betriebssystems für Schaltflächen, Menüs und Fenster folgen. ## Theme names and descriptions used in the Themes panel in about:addons diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/de/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/de/mail/chrome/messenger/addons.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/chrome/messenger/addons.properties 2022-04-15 07:51:37.000000000 +0000 @@ -97,17 +97,16 @@ # LOCALIZATION NOTE (addonInstallErrorBlocklisted): %S is add-on name addonInstallErrorBlocklisted=%S konnte nicht installiert werden, da es ein hohes Risiko bezüglich Stabilität und Sicherheit darstellt. -# LOCALIZATION NOTE (webextPerms.header) -# This string is used as a header in the webextension permissions dialog, +# LOCALIZATION NOTE (webextPerms.header,webextPerms.headerWithPerms,webextPerms.headerUnsigned,webextPerms.headerUnsignedWithPerms) +# These strings are used as headers in the webextension permissions dialog, # %S is replaced with the localized name of the extension being installed. # See https://bug1308309.bmoattachments.org/attachment.cgi?id=8814612 # for an example of the full dialog. -# Note, this string will be used as raw markup. Avoid characters like <, >, & +# Note, these strings will be used as raw markup. Avoid characters like <, >, & webextPerms.header=%S hinzufügen? # %S is brandShortName webextPerms.experimentWarning=Böswillige Add-ons können private Informationen stehlen oder Ihren Computer übernehmen. Installieren Sie dieses Add-on nur, wenn Sie der Quelle vertrauen. - webextPerms.headerWithPerms=%S hinzufügen? Diese Erweiterung wird folgende Berechtigungen erhalten: webextPerms.headerUnsigned=%S hinzufügen? Diese Erweiterung wurde nicht verifiziert. Böswillige Erweiterungen können private Informationen stehlen oder Ihren Computer übernehmen. Fügen Sie diese nur hinzu, wenn Sie der Quelle vertrauen. webextPerms.headerUnsignedWithPerms=%S hinzufügen? Diese Erweiterung wurde nicht verifiziert. Böswillige Erweiterungen können private Informationen stehlen oder Ihren Computer übernehmen. Fügen Sie diese nur hinzu, wenn Sie der Quelle vertrauen. Diese Erweiterung wird folgende Berechtigungen erhalten: @@ -226,6 +225,18 @@ # hosts for which this webextension is requesting permission. webextPerms.hostDescription.tooManySites=Auf Ihre Daten für #1 andere Seite zugreifen;Auf Ihre Daten für #1 andere Seiten zugreifen +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextSitePerms.headerWithPerms=%1$S hinzufügen? Diese Erweiterung gibt %2$S die folgenden Fähigkeiten: +webextSitePerms.headerUnsignedWithPerms=%1$S hinzufügen? Diese Erweiterung wurde nicht verifiziert. Böswillige Erweiterungen können private Informationen stehlen oder Ihren Computer übernehmen. Fügen Sie diese nur hinzu, wenn Sie der Quelle vertrauen. Diese Erweiterung gibt %2$S die folgenden Fähigkeiten: + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties +webextSitePerms.description.midi=Auf MIDI-Geräte zugreifen +webextSitePerms.description.midi-sysex=Auf MIDI-Geräte mit SysEx-Unterstützung zugreifen + # LOCALIZATION NOTE (webext.defaultSearch.description) # %1$S is replaced with the localized named of the extension that is asking to change the default search engine. # %2$S is replaced with the name of the current search engine diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/chrome/messenger/chat.properties thunderbird-91.8.1+build1/l10n/de/mail/chrome/messenger/chat.properties --- thunderbird-91.7.0+build2/l10n/de/mail/chrome/messenger/chat.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/chrome/messenger/chat.properties 2022-04-15 07:51:37.000000000 +0000 @@ -24,6 +24,17 @@ buddy.authRequest.deny.label=Ablehnen buddy.authRequest.deny.accesskey=l +## LOCALIZATION NOTE (buddy.verificationRequest): +# Strings used in a notification bar at the top of the chat tab when someone +# sends a verification request for end-to-end encryption keys. +# %S is replaced with the display name of the user or, if this is to verify a +# session of yourself, a string that identifies the session. +buddy.verificationRequest.label=%S fragt eine gegenseitige Bestätigung Ihrer Identitäten an. +buddy.verificationRequest.allow.label=Bestätigung starten +buddy.verificationRequest.allow.accesskey=s +buddy.verificationRequest.deny.label=Ablehnen +buddy.verificationRequest.deny.accesskey=A + # LOCALIZATION NOTE (buddy.deletePrompt.title): # %S here will be replaced by the alias (or username) of a buddy about # to be removed from the buddy list. diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/am-im.ftl thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/am-im.ftl --- thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/am-im.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/am-im.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -4,3 +4,20 @@ account-settings-title = Authentifizierungs-Einstellungen account-channel-title = Standardräume + +chat-autologin = + .label = Automatisches Verbinden beim Start + +chat-encryption-generic = Allgemein +chat-encryption-log = + .label = Ende-zu-Ende-verschlüsselte Nachrichten ebenfalls in Gesprächsprotokoll aufnehmen +chat-encryption-label = Eingebaute Ende-zu-Ende-Verschlüsselung +chat-encryption-description = { $protocol } unterstützt die Ende-zu-Ende-Verschlüsselung von Chat-Nachrichten. Dies verhindert das Mitlesen der Nachrichten durch Dritte. Zur Unterstützung der Verschlüsselung ist eventuell unten eine Einrichtung nötig. +chat-encryption-status = Verschlüsselungsstatus +chat-encryption-placeholder = Verschlüsselung wurde nicht gestartet. +chat-encryption-sessions = Sitzungen +chat-encryption-sessions-description = Damit die Ende-zu-Ende-Verschlüsselung wie erwartet funktioniert, müssen Sie den anderen Sitzungen vertrauen, welche derzeit mit Ihrem Konto angemeldet sind. Dabei wird zum Bestätigen einer Sitzung eine Interaktion mit deren Client benötigt. Das Bestätigen des Vertrauens in eine Sitzung führt eventuell dazu, dass { -brand-short-name } allen Sitzungen vertraut, dem diese Sitzung bereits vertraute. +chat-encryption-session-verify = bestätigen + .title = Identität der Sitzung bestätigen +chat-encryption-session-trusted = vertraut + .title = Identität der Sitzung wurde bestätigt. diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/connection.ftl thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/connection.ftl --- thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/connection.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/connection.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -29,6 +29,15 @@ connection-disable-extension = .label = Erweiterung deaktivieren +disable-extension-button = Erweiterung deaktivieren + +# Variables: +# $name (String) - The extension that is controlling the proxy settings. +# +# The extension-icon is the extension's icon, or a fallback image. It should be +# purely decoration for the actual extension name, with alt="". +proxy-settings-controlled-by-extension = Die Erweiterung " { $name }" kontrolliert, wie { -brand-short-name } mit dem Internet verbindet. + connection-proxy-legend = Proxies für den Zugriff auf das Internet konfigurieren proxy-type-no = diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/dock-options.ftl thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/dock-options.ftl --- thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/dock-options.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/dock-options.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -6,6 +6,10 @@ .title = Dock-Symbol - Einstellungen .style = width: 35em; +dock-options-show-badge = + .label = Zähler am Dock-Symbol anzeigen + .accesskey = Z + bounce-system-dock-icon = .label = Dock-Symbol beim Eingang neuer Nachrichten animieren .accesskey = a @@ -24,3 +28,5 @@ .accesskey = n notification-settings-info = Der Zähler kann in der Mitteilungen-Ansicht der Systemeinstellungen deaktiviert werden. + +notification-settings-info2 = Der Zähler kann in der Mitteilungen-Ansicht der Systemeinstellungen deaktiviert werden. diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/preferences.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/preferences.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -7,6 +7,8 @@ preferences-doc-title = Einstellungen +preferences-doc-title2 = Einstellungen + category-list = .aria-label = Kategorien @@ -168,10 +170,19 @@ add-search-engine = .label = Aus Datei hinzufügen .accesskey = D +add-web-search-engine = + .label = Hinzufügen… + .accesskey = H remove-search-engine = .label = Entfernen .accesskey = f +add-opensearch-provider-title = OpenSearch-Anbieter hinzufügen +add-opensearch-provider-text = Geben Sie die Adresse des hinzuzufügenden OpenSearch-Anbieters ein. Verwenden Sie entweder die Adresse der OpenSearch-Definitionsdatei oder eine Webadresse, auf der sie sich automatisch erkennen lässt. + +adding-opensearch-provider-failed-title = Hinzufügen des OpenSearch-Anbieters fehlgeschlagen +adding-opensearch-provider-failed-text = OpenSearch-Anbieter unter { $url } konnte nicht hinzugefügt werden. + minimize-to-tray-label = .label = { -brand-short-name } beim Minimieren in die Infoleiste verschieben .accesskey = M @@ -199,6 +210,8 @@ notification-settings = Benachrichtigungen und Standardton können in der Mitteilungszentrale der Systemeinstellungen deaktiviert werden. +notification-settings2 = Benachrichtigungen und Standardton können in der Mitteilungszentrale der Systemeinstellungen deaktiviert werden. + animated-alert-label = .label = Eine Benachrichtigung anzeigen .accesskey = B @@ -253,6 +266,10 @@ .label = Sanften Bildlauf aktivieren .accesskey = f +browsing-gtk-use-non-overlay-scrollbars = + .label = Bildlaufleisten immer anzeigen + .accesskey = B + system-integration-legend = Systemintegration always-check-default = .label = Beim Starten prüfen, ob { -brand-short-name } als Standard-Anwendung registriert ist @@ -413,8 +430,12 @@ type-column-label = Dateityp +type-column-header = Dateityp + action-column-label = Aktion +action-column-header = Aktion + save-to-label = .label = Dateien speichern unter .accesskey = s @@ -889,6 +910,20 @@ ## Preferences UI Search Results +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input2 = + .style = width: 15.4em + .placeholder = In Einstellungen suchen + +## Settings UI Search Results + search-results-header = Suchergebnisse # `` will be replaced by the search term. @@ -896,5 +931,11 @@ [windows] Keine Treffer in den Einstellungen für "". *[other] Keine Treffer in den Einstellungen für "". } + +# `` will be replaced by the search term. +search-results-empty-message2 = { PLATFORM() -> + [windows] Keine Treffer in den Einstellungen für "". + *[other] Keine Treffer in den Einstellungen für "". +} search-results-help-link = Benötigen Sie Hilfe? Dann besuchen Sie die Hilfeseite für { -brand-short-name }. diff -Nru thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/receipts.ftl thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/receipts.ftl --- thunderbird-91.7.0+build2/l10n/de/mail/messenger/preferences/receipts.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/mail/messenger/preferences/receipts.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -9,30 +9,54 @@ .label = Immer eine Empfangsbestätigung anfordern .accesskey = m +return-receipt-checkbox-control = + .label = Beim Senden von Nachrichten immer eine Empfangsbestätigung anfordern + .accesskey = m + receipt-arrive-label = Wenn eine Empfangsbestätigung ankommt: receipt-leave-radio = .label = Im Posteingang belassen .accesskey = P +receipt-leave-radio-control = + .label = Im Posteingang belassen + .accesskey = P + receipt-move-radio = .label = In den Ordner für gesendete Nachrichten verschieben .accesskey = O +receipt-move-radio-control = + .label = In den Ordner für gesendete Nachrichten verschieben + .accesskey = O + receipt-request-label = Wenn aufgefordert wird, eine Empfangsbestätigung zu senden: receipt-return-never-radio = .label = Nie eine Empfangsbestätigung senden .accesskey = N +receipt-return-never-radio-control = + .label = Nie eine Empfangsbestätigung senden + .accesskey = N + receipt-return-some-radio = .label = Bei manchen Nachrichten Empfangsbestätigungen erlauben .accesskey = B +receipt-return-some-radio-control = + .label = Bei manchen Nachrichten Empfangsbestätigungen erlauben + .accesskey = B + receipt-not-to-cc = .value = Wenn ich nicht in der An- oder CC-Zeile stehe: .accesskey = W +receipt-not-to-cc-label = + .value = Wenn ich nicht in der An- oder CC-Zeile stehe: + .accesskey = W + receipt-send-never-label = .label = Nie senden @@ -46,6 +70,14 @@ .value = Wenn der Absender außerhalb meiner Domain ist: .accesskey = E +sender-outside-domain-label = + .value = Wenn der Absender außerhalb meiner Domain ist: + .accesskey = E + other-cases-label = .value = In allen anderen Fällen: .accesskey = n + +other-cases-text-label = + .value = In allen anderen Fällen: + .accesskey = n diff -Nru thunderbird-91.7.0+build2/l10n/de/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/de/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/de/netwerk/necko.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/netwerk/necko.properties 2022-04-15 07:51:37.000000000 +0000 @@ -51,11 +51,11 @@ # LOCALIZATION NOTE(CookieRejectedNonRequiresSecure2): %1$S is the cookie name. Do not localize "SameSite=None" and "secure". CookieRejectedNonRequiresSecure2=Cookie "%1$S" abgelehnt, weil es das "SameSite=None"-Attribut besitzt, aber das "secure"-Attribut fehlt. # LOCALIZATION NOTE(CookieRejectedNonRequiresSecureForBeta2): %1$S is the cookie name. %2$S is a URL. Do not localize "SameSite", "SameSite=None" and "secure". -CookieRejectedNonRequiresSecureForBeta2=Das Cookie "%1$S" wird in Zukunft bald abgelehnt werden, da es für das Attribut "SameSite" entweder "None" oder einen ungültigen Wert angibt, ohne das "secure"-Attribut zu verwenden. Weitere Informationen zum "SameSite"-Attribut finden Sie unter %2$S. +CookieRejectedNonRequiresSecureForBeta2=Das Cookie "%1$S" wird bald abgelehnt werden, da es für das Attribut "SameSite" entweder "None" oder einen ungültigen Wert angibt, ohne das "secure"-Attribut zu verwenden. Weitere Informationen zum "SameSite"-Attribut finden Sie unter %2$S. # LOCALIZATION NOTE(CookieLaxForced2): %1$S is the cookie name. Do not localize "SameSite", "Lax" and "SameSite=Lax". CookieLaxForced2=Die "SameSite"-Richtlinie für das Cookie "%1$S" wurde auf "Lax" gesetzt, weil es über kein "SameSite"-Attribut verfügt und "SameSite=Lax" der Standardwert für dieses Attribut ist. # LOCALIZATION NOTE(CookieLaxForcedForBeta2): %1$S is the cookie name. %2$S is a URL. Do not localize "SameSite", "Lax" and "SameSite=Lax", "SameSite=None". -CookieLaxForcedForBeta2=Das Cookie "%1$S" verfügt über keinen gültigen Wert für das "SameSite"-Attribut. In Zukunft werden bald Cookies ohne das "SameSite"-Attribut oder mit einem ungültigen Wert dafür als "Lax" behandelt. Dadurch wird das Cookie nicht länger an Kontexte gesendet, die zu einem Drittanbieter gehören. Falls Ihre Anwendung das Cookie in diesen Kontexten benötigt, fügen Sie bitte das Attribut "SameSite=None" zu ihm hinzu. Weitere Informationen zum "SameSite"-Attribut finden Sie unter %2$S. +CookieLaxForcedForBeta2=Das Cookie "%1$S" verfügt über keinen gültigen Wert für das "SameSite"-Attribut. Bald werden Cookies ohne das "SameSite"-Attribut oder mit einem ungültigen Wert dafür als "Lax" behandelt. Dadurch wird das Cookie nicht länger an Kontexte gesendet, die zu einem Drittanbieter gehören. Falls Ihre Anwendung das Cookie in diesen Kontexten benötigt, fügen Sie bitte das Attribut "SameSite=None" zu ihm hinzu. Weitere Informationen zum "SameSite"-Attribut finden Sie unter %2$S. # LOCALIZATION NOTE(CookieSameSiteValueInvalid2): %1$S is cookie name. Do not localize "SameSite", "Lax", "Strict" and "None" CookieSameSiteValueInvalid2=Ungültiger Wert für das "SameSite"-Attribut des Cookies "%1$S". Unterstützte Werte sind: "Lax", "Strict", "None". # LOCALIZATION NOTE (CookieOversize): %1$S is the cookie name. %2$S is the number of bytes. "B" means bytes. @@ -63,7 +63,7 @@ # LOCALIZATION NOTE (CookiePathOversize): %1$S is the cookie name. %2$S is the number of bytes. "B" means bytes. CookiePathOversize=Das Cookie "%1$S" ist ungültig, da der Pfad zu groß ist. Die maximale Größe beträgt %2$S Bytes. # LOCALIZATION NOTE (CookieSchemefulRejectForBeta): %1$S is the cookie name. %2$S is the hostname. -CookieSchemefulRejectForBeta=Das Cookie “%1$S” wird bald als Cross-Site-Cookie gegen “%2$S” behandelt, da das Schema nicht übereinstimmt. +CookieSchemefulRejectForBeta=Das Cookie "%1$S" wird bald als Cross-Site-Cookie gegen "%2$S" behandelt, da das Schema nicht übereinstimmt. # LOCALIZATION NOTE (CookieSchemefulReject): %1$S is the cookie name. %2$S is the hostname. CookieSchemefulReject=Das Cookie “%1$S” wurde als Cross-Site-Cookie gegen “%2$S” behandelt, da das Schema nicht übereinstimmt. # LOCALIZATION NOTE (CookieRejectedByPermissionManager): %1$S is the cookie response header. @@ -88,3 +88,6 @@ CookieRejectedExpired=Das Cookie "%1$S" wurde abgelehnt, da es bereits abgelaufen ist. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Das Cookie "%1$S" wurde abgelehnt, weil es sich in einem seitenübergreifenden Kontext befindet und sein "SameSite" auf "Lax" oder "Strict" gesetzt ist. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Warnung: "%1$S" sollte nicht mehr verwendet werden, bitte verwenden Sie "%2$S". diff -Nru thunderbird-91.7.0+build2/l10n/de/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/de/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/de/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:51:37.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Leseansicht schließen @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Helles Farbschema aboutReader.toolbar.colorschemedark = Dunkles Farbschema aboutReader.toolbar.colorschemesepia = Sepia-Farbschema +aboutReader.toolbar.colorschemeauto = Automatisches Farbschema diff -Nru thunderbird-91.7.0+build2/l10n/de/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/de/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/de/toolkit/chrome/global/narrate.properties 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/toolkit/chrome/global/narrate.properties 2022-04-15 07:51:37.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Anhören back = Zurück start = Wiedergeben stop = Anhalten +# %S is the keyboard shortcut for the start command +start-label = Wiedergeben (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Anhalten (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Vor speed = Geschwindigkeit selectvoicelabel = Stimme: diff -Nru thunderbird-91.7.0+build2/l10n/de/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/de/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/de/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } Bild + *[other] { $frames } Bilder + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } Kanal + *[other] { $channels } Kanäle + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/de/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/de/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/de/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -9,11 +9,6 @@ experimental-features-css-masonry-description = Aktiviert die Unterstützung für die experimentelle CSS-Mauerwerk-Darstellung. Weitere Informationen zu den Grundlagen dieser Funktion sind in dieser Erläuterung zu finden. Rückmeldung kann per Kommentar in diesem Github Issue oder in diesem Bug gegeben werden. # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. -experimental-features-css-cascade-layers = - .label = CSS: Cascade Layers -experimental-features-css-cascade-layers-description = Aktiviert die Unterstützung für CSS Cascade Layers. Weitere Informationen sind in der Spezifikation zu finden, die noch in Arbeit ist. Melden Sie Fehler im Zusammenhang mit dieser Funktion als blockierend für Bug 1699215. -# The title of the experiment should be kept in English as it may be referenced -# by various online articles and is technical in nature. experimental-features-web-gpu2 = .label = Web API: WebGPU experimental-features-web-gpu-description2 = Diese neue API bietet eine Low-Level-Unterstützung für die Durchführung von Berechnungen und Grafikdarstellung mit der Graphics Processing Unit (GPU) des Geräts oder Computers des Benutzers. Die Spezifikation ist noch in Arbeit. Weitere Informationen erhalten Sie im Bug 1602129. @@ -94,3 +89,7 @@ experimental-features-ime-search = .label = Adressleiste: Ergebnisse während der IME-Komposition anzeigen experimental-features-ime-search-description = Ein IME (Input Method Editor) ist ein Werkzeug, mit dem Sie komplexe Symbole, wie sie in ostasiatischen oder indischen Schriftsprachen verwendet werden, über eine Standardtastatur eingeben können. Durch Aktivieren dieses Experiments bleibt die Adressleisten-Ansicht geöffnet, wodurch Suchergebnisse und Vorschläge angezeigt werden, während IME zur Texteingabe verwendet wird. Beachten Sie, dass der IME möglicherweise ein Fenster anzeigt, das die Ergebnisse der Adressleiste verdeckt. Daher wird diese Einstellung nur für IME empfohlen, die diese Art von Fenster nicht verwenden. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name } 100 User-Agent-String +experimental-features-firefox-100-description = Lässt { -brand-short-name } einen User-Agent-String an Websites senden, der vorgibt, { -brand-product-name } Version 100 zu sein. Verwenden Sie diese Einstellung, um zu testen, ob Websites abstürzen, wenn { -brand-short-name } eine dreistellige Versionsnummer erreicht. { -brand-product-name } 100 soll im Mai 2022 veröffentlicht werden - beginnen Sie jetzt mit dem Testen Ihrer Websites! diff -Nru thunderbird-91.7.0+build2/l10n/de/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/de/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/de/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:36:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/de/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:51:37.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socket # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Isolierter IPC-Aktor ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/dsb/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/dsb/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/dsb/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Priwatnosć: Priwatne tšojenje calendar-editable-item-privacy-icon-confidential = .alt = Priwatnosć: Jano cas a datum pokazaś +calendar-editable-item-recurrence = + .alt = Wóspjetowanje +calendar-editable-item-recurrence-exception = + .alt = Wóspjetowańske wuwześe calendar-editable-item-todo-icon-task = .alt = Nadawk calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/dsb/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/dsb/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/dsb/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:51:45.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } jo was pśepšosył do: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Składowaś +calendar-invitation-panel-accept-button = Jo +calendar-invitation-panel-decline-button = Ně +calendar-invitation-panel-tentative-button = Snaź +calendar-invitation-panel-reply-status = * Hyšći njejsćo rozsuźił abo wótegronił +calendar-invitation-panel-prop-title-when = Gdy: +calendar-invitation-panel-prop-title-location = Městno: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Wobźělniki: +calendar-invitation-panel-prop-title-description = Wopisanje: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } jo + [DECLINED] { $count } ně + [TENTATIVE] { $count } snaź + [NEEDS-ACTION] { $count } felujucych + [TOTAL] { $count } wobźělniki + *[OTHER] { $count } drugich + } diff -Nru thunderbird-91.7.0+build2/l10n/dsb/chat/matrix.properties thunderbird-91.8.1+build1/l10n/dsb/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/dsb/chat/matrix.properties 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/chat/matrix.properties 2022-04-15 07:51:44.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S jo anulěrował wobkšuśenje ze slědujuceje pśicyny: %2$S message.verification.done=Pśeglědanje jo dokóńcone. +message.decryptionError=Wopśimjeśe toś teje powěsći njedajo se dešifrěrowaś. Aby koděrowańske kluce ze swójich drugich rědow pominał, kliknišo z pšaweju tastu na powěsć. +message.decrypting=Dešifrěrujo se… +message.redacted=Powěsć jo se pśeźěłała. + +# Label in the message context menu +message.action.requestKey=Kluce znowego pominaś +message.action.redact=Pśeźěłaś +message.action.report=Powěsć k wěsći daś +message.action.retry=Znowego słaś +message.action.cancel=Powěsć anulěrowaś + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Pśi słanju wašeje powěsći „%1$S“ jo zmólka nastała. diff -Nru thunderbird-91.7.0+build2/l10n/dsb/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/dsb/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/dsb/devtools/client/aboutdebugging.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/devtools/client/aboutdebugging.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Pytanje zmólkow - konfiguracija - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Pytanje zmólkow - běžny cas / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Toś ten { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Zarědowanje - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB zmóžnjony - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB znjemóžnjony - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Zwězany # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Zwisk źělony - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = Žedne rědy namakane - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Zwězaś - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Zwězujo se… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Zwisk njejo se raźił. - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = Zwisk hyšći njejo nawězany, pśespytajśo za powěsćami w celowem wobglědowaku - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = Cas zwiska pśekšocony - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Caka se na wobglědowak… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Źělone - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Pomoc za pytanje zmólkow - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Symbol pomocy - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Rědy aktualizěrowaś @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Zarědowanje - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Konfigurěrujśo zwiskowu metodu, z kótarejuž cośo swój rěd znazdala za zmólkami pśespytowaś. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Wužywajśo { about-debugging-this-firefox-runtime-name }, aby rozšyrjenja a service workers toś teje wersije { -brand-shorter-name } za zmólkami pśepytował. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Z rědom zwězaś - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Gaž se to zmóžnja, se trěbne komponenty za pytanje zmólkow USB Android ześěgnu a se { -brand-shorter-name } pśidaju. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = USB-rědy zmóžniś - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = USB-rědy znjemóžniś - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Aktualizěrujo se… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Zmóžnjony about-debugging-setup-usb-status-disabled = Znjemóžnjony about-debugging-setup-usb-status-updating = Aktualizěrujo se… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Wuwijaŕski meni na wašom rěźe Android zmóžniś. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Pytanje zmólkow USB we wuwijaŕskem meniju Android zmóžniś. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Pytanje zmólkow USB w Firefox na rěźe Android zmóžniś. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Zwězajśo rěd Android ze swójim licadłom. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Maśo problemy pśi zwězowanju z USB-rědom? Problem rozwězaś - # Network section of the Setup page about-debugging-setup-network = .title = Seśowa adresa - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Maśo problemy pśi zwězowanju pśez seśowu adresu? Problem rozwězaś - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Pśidaś - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = Seśowe adrese hyšći njejsu se pśidali. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Host - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Wótwónoźeś - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Njepłaśiwy "{ $host-value }": Wótcakany format jo "hostowe mě:portowy numer" - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Procese - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Profilowe wugbaśe - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Konfiguracija wašogo wobglědowaka njejo kompatibelna ze service workers. Dalšne informacije - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = Zwězany wobglědowak ma staru wersiju ({ $runtimeVersion }). Pódpěrana minimalna wersija jo ({ $minVersion }). To jo njepódpěrana konfiguracija a móžo zawinowaś, až wuwijaŕske rědy njefunkcioněruju. Pšosym aktualizěrujśo zwězany wobglědowak. Rozwězanje problemow - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = Toś ta wersija Firefox njamóžo Firefox za Android (68) za zmólkami pśeglědowaś. Pórucamy, až Firefox za Android Nightly na swójom telefonje za testowanje instalěrujośo. Dalšne drobnostki - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = Zwězany wobglědowak jo aktualnjejšy ({ $runtimeVersion }, buildID { $runtimeID }) lěc waš { -brand-shorter-name } ({ $localVersion }, buildID { $localID }). To jo njepódpěrana konfiguracija a móžo zawinowaś, až wuwijaŕske rědy njefunkcioněruju. Pšosym aktualizěrujśo Firefox. Rozwězanje problemow - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Zwisk źěliś - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Zwiskowe napominanje zmóžniś - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Zwiskowe napominanje znjemóžniś - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Profilowaŕ - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Hyšći nic. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Pśespytowaś - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Nachylny dodank zacytaś… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = Pśi instalěrowanju nachylnego dodanka jo zmólka nastała. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Znowego zacytaś - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Wótwónoźeś - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Slězynowy skript dokóńcyś # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Dataju manifest.json abo archiw .xpi/.zip wubraś - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Toś to WebExtension ma nachylny ID. Dalšne informacije - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = URL manifesta - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = Nutśikowny UUID - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Městno - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = ID rozšyrjenja - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Slězynowy skript +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Běžy +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Zastajony # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push .disabledTitle = Push service worker jo tuchylu znjemóžnjony za multiprocesowy { -brand-shorter-name } - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Start .disabledTitle = Start service worker jo tuchylu znjemóžnjony za multiprocesowy { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Registrěrowanje wótpóraś - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Słuchanje na tšojenja Fetch - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = Žedno słuchanje na tšojenja Fetch - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Běžy - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Zastajony - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Registrěrujo se - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Wobceŕk - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Słužba za eksterne powěsći - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = Pśeglědanje service worker jo tuchylu znjemóžnjone za multiprocesowy { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Rejtarik njejo se dopołnje zacytał a njedajo se pśeglědowaś - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Głowny proces - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Głowny proces za celowy wobglědowak - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Multiprocesowe rědy - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Głowny proces a wopśimjeśowe procese za celowy wobglědowak - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Powěźeńku zacyniś - # Label text used for the error details of message component. about-debugging-message-details-label-error = Zmólkowe drobnostki - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Warnowańske drobnostki - # Label text used for default state of details of message component. about-debugging-message-details-label = Drobnostki diff -Nru thunderbird-91.7.0+build2/l10n/dsb/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/dsb/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/dsb/devtools/client/compatibility.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/devtools/client/compatibility.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (eksperimentelny) compatibility-issue-prefixneeded = (prefiks trjebny) compatibility-issue-deprecated-experimental = (zestarjony, eksperimentelny) - compatibility-issue-deprecated-prefixneeded = (zestarjony, prefiks trjebny) compatibility-issue-experimental-prefixneeded = (eksperimentelny, prefiks trjebny) compatibility-issue-deprecated-experimental-prefixneeded = (zestarjony, eksperimentelny, prefiks trjebny) @@ -45,7 +44,14 @@ [few] { $number } wustupowanja *[other] { $number } wustupowanjow } - compatibility-no-issues-found = Žedne problemy kompatibelnosći namakane. compatibility-close-settings-button = .title = Nastajenja zacyniś +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Problemy kompatibelnosći w: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/dsb/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/dsb/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/dsb/devtools/client/netmonitor.properties 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/devtools/client/netmonitor.properties 2022-04-15 07:51:44.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=Znamuškowy rjeśazk „%S“ jo se wótwónoźeł ze zachopjeńka JSON, kótaryž se dołojce pokazujo + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Napšašowański znamuškowy rjeśazk: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL-parametry + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Głowy napšašowanja: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Głowy + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=mě + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=gódnota + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Wopśimjeśe + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=nakładna śěža + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Wopśimjeśe napšašowanja: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Pśetergnuś +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Lašowaś + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Zapisk wótwónoźeś + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Slědk diff -Nru thunderbird-91.7.0+build2/l10n/dsb/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/dsb/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/dsb/devtools/client/toolbox-options.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/devtools/client/toolbox-options.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Daloke pytanje za zmólkami options-enable-remote-tooltip2 = .title = Gaž toś to nastajenje zmóžnjaśo, se instanca wobglědowaka znazdala za zmólkami pśepytujo +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Swójske formatěrowaki zmóžniś +options-enable-custom-formatters-tooltip = + .title = Gaž toś to nastajenje zmóžnjaśo, směju sedła swójske formatěrowaki za DOM-objekty definěrowaś # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Service worker pśez HTTP zmóžniś (gaž rědy su wócynjone) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/dsb/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/dsb/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/dsb/devtools/client/webconsole.properties 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/devtools/client/webconsole.properties 2022-04-15 07:51:44.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=Dataja +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Wšykne powěsći kopěrowaś +webconsole.menu.copyAllMessages.accesskey=k + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Wšykne powěsći do dataje składowaś +webconsole.menu.saveAllMessagesFile.accesskey=W + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/dsb/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/dsb/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/dsb/dom/chrome/dom/dom.properties 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/dom/chrome/dom/dom.properties 2022-04-15 07:51:45.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Pšosym zapódajśo URL. FormValidationInvalidDate=Pšosym zapódajśo płaśiwy datum. FormValidationInvalidTime=Zapódajśo pšosym płaśiwy cas. +FormValidationInvalidDateTime=Pšosym zapódajśo płaśiwy datum a cas. +FormValidationInvalidDateMonth=Pšosym zapódajśo płaśiwy mjasec. +FormValidationInvalidDateWeek=Pšosym zapódajśo płaśiwy tyźeń. FormValidationPatternMismatch=Pšosym wužyjśo pominany format. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Pšosym wužyjśo pominany format: %S. diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/dsb/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/dsb/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:51:44.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/aboutDialog.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Nowe funkcije a změny diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/aboutImport.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/aboutImport.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Wubjeŕśo, wótkulž maju se konta, adresniki, kalendarje a druge daty importěrowaś: import-address-book = Adresnikowu dataju importěrowaś import-calendar = Dataju kalendarja importěrowaś +export-profile = Eksportěrowaś ## Buttons button-cancel = Pśetergnuś button-back = Slědk button-continue = Dalej +button-export = Eksportěrowaś ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Z { $app } importěrowaś @@ -26,17 +33,52 @@ profile-file-picker-dir = Wubjeŕśo profilowy zarědnik profile-file-picker-zip = Wubjeŕśo zip-dataju (mjeńšu ako 2 GB) items-pane-title = Wubjeŕśo, což ma se importěrowaś -items-pane-desc = Importěrowaś z +items-pane-source = Žrědłowe městno: items-pane-checkbox-accounts = Konta a nastajenja items-pane-checkbox-address-books = Adresniki items-pane-checkbox-calendars = Kalendarje items-pane-checkbox-mail-messages = Mejlki +## Import from address book file steps + +import-from-addr-book-file-desc = Wubjeŕśo dataju, kótaruž cośo importěrowaś: +addr-book-csv-file = Dataja źělona pśez komu abo rejtarik (.csv, .tsv) +addr-book-ldif-file = Dataja LDIF (.ldif) +addr-book-vcard-file = Dataja vCard (.vcf, .vcard) +addr-book-sqlite-file = Dataja datoweje banki SQLite (.sqlite) +addr-book-mab-file = Dataja datoweje banki Mork (.mab) +addr-book-file-picker = Adresnikowu dataju wubraś +addr-book-csv-field-map-title = Pólnym mjenjam wótpowědowaś +addr-book-csv-field-map-desc = Wubjeŕśo póla adresnika, kótarež žrědłowym pólam wótpowěduju. Znjemóžniśo póla, kótarež njocośo importěrowaś. +addr-book-directories-pane-title = Wubjeŕśo zapis, kótaryž cośo importěrowaś do: +addr-book-directories-pane-source = Žrědłowa dataja: +addr-book-import-into-new-directory = Nowy zarědnik załožyś + ## Import dialog progress-pane-title = Importěrowanje +progress-pane-importing = Importěrowanje +progress-pane-exporting = Eksportěrowanje +progress-pane-finished-desc = Dokóńcone. progress-pane-restart-desc = Startujśo znowego, aby importěrowanje dokóńcył. error-pane-title = Zmólka error-message-zip-file-too-big = Wubrana zip-dataja jo wětša ako 2 GB. Pšosym rozpakujśo ju nejpjerwjej, a importěrujśo wopśimjeśe z rozpakowanego zarědnika město togo. error-message-extract-zip-file-failed = Zip-dataja njedajo se rozpakowaś. Pšosym rozpakujśo ju manuelnje a importěrujśo ju pón město togo z ekstrahěrowanego zarědnika. error-message-failed = Importěrowanje njejo se njenaźejucy raźiło, dalšne informacije namakajośo snaź w zmólkowej konsoli. +error-export-failed = Eksportěrowanje njejo se njenaźejucy raźiło, dalšne informacije namakajośo snaź w zmólkowej konsoli. + +## element + +csv-first-row-contains-headers = Prědna smužka wopśimujo pólowe mjenja +csv-source-field = Žrědłowa dataja +csv-source-first-record = Prědna datowa sajźba +csv-source-second-record = Druga datowa sajźba +csv-target-field = Pólo adresnika + +## Export tab + +export-profile-desc = Eksportěrujśo e-mailowe konta, mejlki, adresniki, nastajenja do zip-dataje. Jolic trjeba, móžośo zip-dataju importěrowaś, aby swój profil wótnowił. +export-profile-desc2 = Jolic waš aktualny profil jo wětšy ako 2 GB, naraźujomy, až jen zawěsćujośo. +export-open-profile-folder = Profilowy zarědnik wócyniś +export-file-picker = Ako zip-dataju eksportěrowaś +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Nowy CardDAV-adresnik - +carddav-window-title = Nowy CardDAV-adresnik carddav-dialog = .buttonlabelaccept = Dalej .buttonaccesskeyaccept = D - carddav-username-label = .value = Wužywarske mě: .accesskey = u - carddav-location-label = .value = Městno: .accesskey = M carddav-location = .default-placeholder = URL abo hostowe mě adresnikowego serwera - carddav-loading = Konfiguracija se pśepytujo… carddav-known-incompatible = { $url } jo znaty za to, až jo inkompatibleny z { -brand-short-name }. carddav-connection-error = Zwisk njejo móžny. carddav-none-found = Njedaju adresniki, kótarež daju se wěstemu kontoju pśidaś. carddav-already-added = Wšykne adresniki za pódane konto su se južo pśidali. - carddav-available-books = K dispoziciji stojece adresniki: diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -144,8 +144,8 @@ about-addressbook-details-home-address-header = Priwatna adresa about-addressbook-details-work-address-header = Słužbna adresa about-addressbook-details-other-info-header = Druge informacije -about-addressbook-prompt-to-save-title = Změny składowaś? -about-addressbook-prompt-to-save = Cośo swóje změny składowaś? +about-addressbook-unsaved-changes-prompt-title = Njeskłaźone změny +about-addressbook-unsaved-changes-prompt = Cośo swóje změny składowaś, nježli až wobźěłowański naglěd spušćaśo? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -93,6 +93,15 @@ .tooltiptext = Pśidankowe wokno pokazaś ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Pśidankowe wokno schowaś ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } pśidank + [one] { $count } pśidank + [two] { $count } pśidanka + [few] { $count } pśidanki + *[other] { $count } pśidankow + } attachment-area-show = .title = Pśidankowe wokno pokazaś ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -256,8 +265,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Tekstowy stil wótwónoźeś -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Jo se nagrało do njeznatego konta Filelink. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } - pśidank Filelink +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = Dataja { $filename } jo se pśipowjesyła ako Filelink. Dajo se z pomocu slědujuego wótkaza ześěgnuś. # Template @@ -272,24 +294,27 @@ *[other] Som zwězał { $count } datajow z toś teju mejlku: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Dalšne informacije wó { $lastLink }. - [two] Dalšne informacije wó { $firstLinks } a { $lastLink }. - [few] Dalšne informacije wó { $firstLinks } a { $lastLink }. - *[other] Dalšne informacije wó { $firstLinks } a { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Dalšne informacije wó { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Dalšne informacije wó { $firstLinks } a { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Pśez gronidło šćitany wótkaz # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = Słužba CloudFile: +cloud-file-template-service-name = Słužba Filelink: cloud-file-template-size = Wjelikosć: cloud-file-template-link = Wótkaz: cloud-file-template-password-protected-link = Pśez gronidło šćitany wótkaz: @@ -313,3 +338,9 @@ cloud-file-rename-error-with-custom-message-title = Pśemjenowanje { $filename } na { $provider } njejo se raźiło # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = { $provider } pśemjenowanje južo nagratych datajow njepódpěra. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Pśidankowa zmólka Filelink +cloud-file-attachment-error = Pśidank { $filename } Filelink njedajo se aktualizěrowaś, dokulaž jogo lokalna dataja jo se pśesunuła abo wulašowała. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Kontowa zmólka Filelink +cloud-file-account-error = Pśidank { $filename } Filelink njedajo se aktualizěrowaś, dokulaž jogo lokalna dataja jo se wulašowała. diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/messenger.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/messenger.ftl 2022-04-15 07:51:45.000000000 +0000 @@ -192,3 +192,64 @@ .title = K rejtarikoju nastajenjow pśejś spaces-toolbar-button-collapse = .title = Rědku źělnych programow schowaś +spaces-toolbar-button-reveal = + .title = Rědku źělnych programow pokazaś +spaces-context-new-tab-item = + .label = W nowem rejtarku wócyniś +spaces-context-new-window-item = + .label = W nowem woknje wócyniś +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = K { $tabName } pśejś +settings-context-open-settings-item = + .label = Nastajenja wócyniś +settings-context-open-account-settings-item = + .label = Kontowe nastajenja wócyniś +settings-context-open-addons-item = + .label = Dodanki a drastwy wócyniś + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Meni źělnych programow wócyniś +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [one] { $count } njecytana powěsć + [two] { $count } njecytanej powěsći + [few] { $count } njecytane powěsći + *[other] { $count } njecytanych powěsćow + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Pśiměriś… +spaces-customize-panel-title = Nastajenja rědki źělnych programow +spaces-customize-background-color = Slězynowa barwa +spaces-customize-icon-color = Tłocaškowa barwa +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Slězynowa barwa wubranego tłocaška +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Barwa wubranego tłocaška +spaces-customize-button-restore = Standard wótnowiś + .accesskey = S +spaces-customize-button-save = Dokóńcony + .accesskey = D diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -16,15 +16,13 @@ .label = Drobnostki wócyniś a akceptancu wobźěłaś… openpgp-one-recipient-status-discover = .label = Nowy abo zaktualizěrowany kluc namakaś - openpgp-one-recipient-status-instruction1 = Aby dostawarjeju powěsć skoděrowanu kóńc do kóńca pósłał, musyśo se jogo zjawny OpenPGP-kluč wobstaraś a jen ako akceptěrowany markěrowaś. openpgp-one-recipient-status-instruction2 = Aby jogo zjawny kluc dostał, importěrujśo jogo z mejlki, kótaruž jo wam pósłał a to jen zasajźijo. Alternatiwnje móžośo wopytaś, jogo zjawny kluc w zapisu namakaś. - openpgp-key-own = Akceptěrowany (wósobinski kluc) openpgp-key-secret-not-personal = Njewužywajobny openpgp-key-verified = Akceptěrowany (wobkšuśony) openpgp-key-unverified = Akceptěrowany (njewobkšuśony) openpgp-key-undecided = Njeakceptěrowany (njerozsuźony) openpgp-key-rejected = Njeakceptěrowany (wótpokazany) - +openpgp-key-expired = Pśepadnjony openpgp-intro = K dispoziciji stojece zjawne kluce za { $key } diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/otr/add-finger.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/otr/add-finger.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Palcowy wótśišć OTR-kluca pśidaś - +otr-add-finger-title = Palcowy wótśišć OTR-kluca pśidaś # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Zapódajśo palcowy wótśišć OTR-kluca za { $name }. - otr-add-finger-fingerprint = Palcowy wótśišć: otr-add-finger-tooltip-error = Njepłaśiwe znamuško jo se zapódało. Jano pismiki ABCDEF a licby su dowólone - otr-add-finger-input = .placeholder = 40 znamuškow dłujki palcowy wótśišć OTR-kluca diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/otr/finger.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/otr/finger.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Zacyniś .title = Do togo wiźone palcowe wótśišće OTR - +otr-finger-title = Do togo wiźone palcowe wótśišće OTR finger-intro = Palcowe wóotśišće OTR-kluca z pjerwjejšnych rozgronow wót kóńca do kóńca. - finger-screen-name = .label = Kontakt finger-verified = .label = Pśespytowański status finger-fingerprint = .label = Palcowy wótśišć - finger-remove = .label = Wubrane wótwónoźeś - finger-remove-all = .label = Wše wótwónoźeś diff -Nru thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/dsb/mail/messenger/preferences/preferences.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/mail/messenger/preferences/preferences.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -116,9 +116,6 @@ .label = Standard wótnowiś .accesskey = S default-search-engine = Standardna pytnica -add-search-engine = - .label = Z dataje pśidaś - .accesskey = Z add-web-search-engine = .label = Pśidaś… .accesskey = P @@ -196,6 +193,9 @@ smooth-scrolling-label = .label = Pólažke pśesuwanje wužywaś .accesskey = l +browsing-gtk-use-non-overlay-scrollbars = + .label = Suwańske rědki pśecej pokazaś + .accesskey = u system-integration-legend = Systemowa integracija always-check-default = .label = Pśi startowanju pśecej kontrolěrowaś, lěc { -brand-short-name } jo standardny e-mailowy program @@ -320,12 +320,6 @@ .accesskey = B search-handler-table = .placeholder = Wopśimjeśowe typy a akcije filtrowaś -type-column-label = - .label = Typ wopśimjeśa - .accesskey = T -action-column-label = - .label = Akcija - .accesskey = A type-column-header = Wopśimjeśowy typ action-column-header = Akcija save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/dsb/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/dsb/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/dsb/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:51:44.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Cytański naglěd zacyniś @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Swětła barwowa šema aboutReader.toolbar.colorschemedark = Śamnowa barwowa šema aboutReader.toolbar.colorschemesepia = Barwowa šema Sepia +aboutReader.toolbar.colorschemeauto = Awtomatiska barwowa šema diff -Nru thunderbird-91.7.0+build2/l10n/dsb/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/dsb/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/dsb/toolkit/chrome/global/narrate.properties 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/toolkit/chrome/global/narrate.properties 2022-04-15 07:51:44.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Słuchaś back = Slědk start = Zachopiś stop = Zastajiś +# %S is the keyboard shortcut for the start command +start-label = Startowaś (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Zastajiś (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Doprědka speed = Malsnosć selectvoicelabel = Głos: diff -Nru thunderbird-91.7.0+build2/l10n/dsb/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/dsb/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/dsb/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -185,6 +185,26 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } wobłuk + [two] { $frames } wobłuka + [few] { $frames } wobłuki + *[other] { $frames } wobłukow + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } kanal + [two] { $channels } kanala + [few] { $channels } kanale + *[other] { $channels } kanalow + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/dsb/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/dsb/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/dsb/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:36:54.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/dsb/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:51:44.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Adresowe pólo: wuslědki za IME-kompoziciju pokazaś experimental-features-ime-search-description = IME (Input Method Editor, editor zapódawańskeje metody) jo rěd, kótaryž wam zmóžnja, kompleksne symbole zapódaś, ako se na pśikład w pódzajtšnoaziskich abo indiskich rěcach wužywaju, z pomocu standardneje tastatury. Gaž toś ten eksperiment zmóžnjaśo, wóstawa wokno adresowego póla wócynjone, kótarež pytańske wuslědki a naraźenja pokazujo, mjaztym až tekst z pomocu IME zapódawaśo. Źiwajśo na to, až IME mógał wokno pokazaś, kótarež wuslědki adresowego póla wopśimujo, togodla se toś to nastajenje jano za IME naraźujo, kótaryž toś ten typ wokna njewužywa. +# Firefox 100 +experimental-features-firefox-100 = + .label = Znamuškowy rjeśazk user-agent { -brand-product-name } 100 +experimental-features-firefox-100-description = Dajśo { -brand-short-name } websedłam znamuškowy rjeśazk user agent słaś, kótaryž se wugranja, až se wo wersiju 100 { -brand-product-name } jadna. Wužywajśo toś to nastajenje, aby testował, lěc se websedła wobškóźuju, gaž { -brand-short-name } ma tśiměstnowy wersijowy numer. Wózjawjenje napšawdnego { -brand-product-name } 100 jo za maj 2022 planowane, testujśo pótakem swóje websydła něnto! diff -Nru thunderbird-91.7.0+build2/l10n/el/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/el/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/el/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Απόρρητο: Ιδιωτική εκδήλωση calendar-editable-item-privacy-icon-confidential = .alt = Απόρρητο: Εμφάνιση μόνο ώρας και ημερομηνίας +calendar-editable-item-recurrence = + .alt = Επανάληψη +calendar-editable-item-recurrence-exception = + .alt = Εξαίρεση επανάληψης calendar-editable-item-todo-icon-task = .alt = Εργασία calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/el/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/el/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/el/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:51:53.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = Ο/Η { $organizer } σάς προσκάλεσε στο: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Αποθήκευση +calendar-invitation-panel-accept-button = Ναι +calendar-invitation-panel-decline-button = Όχι +calendar-invitation-panel-tentative-button = Ίσως +calendar-invitation-panel-reply-status = * Δεν έχετε αποφασίσει ή απαντήσει ακόμα +calendar-invitation-panel-prop-title-when = Πότε: +calendar-invitation-panel-prop-title-location = Τοποθεσία: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Συμμετέχοντες: +calendar-invitation-panel-prop-title-description = Περιγραφή: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } ναι + [DECLINED] { $count } όχι + [TENTATIVE] { $count } ίσως + [NEEDS-ACTION] { $count } εκκρεμούν + [TOTAL] { $count } συμμετέχοντες + *[OTHER] { $count } άλλα + } diff -Nru thunderbird-91.7.0+build2/l10n/el/calendar/chrome/lightning/lightning.dtd thunderbird-91.8.1+build1/l10n/el/calendar/chrome/lightning/lightning.dtd --- thunderbird-91.7.0+build2/l10n/el/calendar/chrome/lightning/lightning.dtd 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/calendar/chrome/lightning/lightning.dtd 2022-04-15 07:51:52.000000000 +0000 @@ -38,7 +38,7 @@ These strings are used in the calendar wizard and the calendar properties dialog, but are only displayed when setting/using a caldav calendar --> - + diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/am-server-advanced.dtd thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/am-server-advanced.dtd --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/am-server-advanced.dtd 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/am-server-advanced.dtd 2022-04-15 07:51:52.000000000 +0000 @@ -20,7 +20,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/am-server-top.dtd thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/am-server-top.dtd --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/am-server-top.dtd 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/am-server-top.dtd 2022-04-15 07:51:53.000000000 +0000 @@ -35,7 +35,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -68,7 +68,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/importMsgs.properties thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/importMsgs.properties --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/importMsgs.properties 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/importMsgs.properties 2022-04-15 07:51:52.000000000 +0000 @@ -284,7 +284,7 @@ # LOCALIZATION NOTE : The %S will get replaced by the name of the import module. ImportFiltersSuccess=Επιτυχής εισαγωγή φίλτρων από %S. # LOCALIZATION NOTE : The %S will get replaced by the name of the import module. -ImportFiltersPartial=Μερική εισαγωγή φίλτρων από %S. Παρακάτω οι προειδοποιήσεις: +ImportFiltersPartial=Έγινε μερική εισαγωγή φίλτρων από το %S. Ακολουθούν προειδοποιήσεις: #Progress strings # LOCALIZATION NOTE : Do not translate the word "%S" below. diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messengercompose/composeMsgs.properties thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messengercompose/composeMsgs.properties --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messengercompose/composeMsgs.properties 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messengercompose/composeMsgs.properties 2022-04-15 07:51:52.000000000 +0000 @@ -81,10 +81,10 @@ smtpClientidPermission=Η απάντηση του διακομιστή εξερχομένων (SMTP) στην εντολή CLIENTID υποδεικνύει ότι η συσκευή σας δεν επιτρέπεται να αποστείλει αλληλογραφία. Ο διακομιστής απάντησε: %s ## LOCALIZATION NOTE (smtpPermSizeExceeded1): argument %d is the Outgoing server (SMTP) size limit -smtpPermSizeExceeded1=Το μέγεθος του μηνύματος που προσπαθείτε να στείλετε υπερβαίνει το όριο μεγέθους (%d bytes) του διακομιστή. Το μήνυμα δεν στάλθηκε: Προσπαθήστε να μειώσετε το μέγεθος του μηνύματος και προσπαθήστε ξανά. +smtpPermSizeExceeded1=Το μέγεθος του μηνύματος που προσπαθείτε να στείλετε υπερβαίνει το όριο μεγέθους (%d bytes) του διακομιστή. Το μήνυμα δεν απεστάλη· μειώστε το μέγεθός του και δοκιμάστε ξανά. ## LOCALIZATION NOTE (smtpPermSizeExceeded2): argument %s is the Outgoing server (SMTP) response -smtpPermSizeExceeded2=Το μέγεθος του μηνύματος που προσπαθείτε να στείλετε υπερβαίνει το όριο μεγέθους του διακομιστή. Το μήνυμα δεν στάλθηκε: Προσπαθήστε να μειώσετε το μέγεθος του μηνύματος και προσπαθήστε ξανά. Ο διακομιστής αποκρίθηκε: %s. +smtpPermSizeExceeded2=Το μέγεθος του μηνύματος που προσπαθείτε να στείλετε υπερβαίνει το όριο μεγέθους του διακομιστή. Το μήνυμα δεν απεστάλη· μειώστε το μέγεθός του και δοκιμάστε ξανά. Ο διακομιστής αποκρίθηκε: %s. ## LOCALIZATION NOTE (smtpSendFailedUnknownServer): argument %S is the Outgoing server (SMTP) smtpSendFailedUnknownServer=Σφάλμα κατά την αποστολή αλληλογραφίας. Ο διακομιστής SMTP %S είναι άγνωστος. Βεβαιωθείτε ότι έχετε εισάγει σωστά τις ρυθμίσεις SMTP και προσπαθήστε ξανά. @@ -137,7 +137,7 @@ genericFailureExplanation=Βεβαιωθείτε ότι οι Προτιμήσεις αλληλογραφίας σας είναι σωστές και προσπαθήστε ξανά. ## LOCALIZATION NOTE (undisclosedRecipients): this string must use only US_ASCII characters -undisclosedRecipients=undisclosed-recipients +undisclosedRecipients=άγνωστοι παραλήπτες # LOCALIZATION NOTE (chooseFileToAttachViaCloud): %1$S is the cloud # provider to save the file to. @@ -436,10 +436,6 @@ ## Using PluralForm (so don't replace the #1). cloudAttachmentCountHeader=Έχω συνδέσει #1 αρχείο σε αυτό το email:;Έχω συνδέσει #1 αρχεία σε αυτό το email: -## LOCALIZATION NOTE(cloudAttachmentListFooter): %1$S is a link, whose text -## contents are the brandFullName of this application. -cloudAttachmentListFooter=Το %1$S διευκολύνει την κοινή χρήση μεγάλων αρχείων μέσω email. - ## LOCALIZATION NOTE(cloudAttachmentListItem): A line of text describing a cloud ## attachment to be inserted into the message body. Do not translate the words ## %1$S, %2$S, %3$S, or %4$S. %1$S is the attachment name, %2$S is its size, diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:51:52.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messenger.dtd thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messenger.dtd --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messenger.dtd 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messenger.dtd 2022-04-15 07:51:52.000000000 +0000 @@ -147,9 +147,9 @@ - + - + @@ -701,7 +701,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messenger.properties thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messenger.properties --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/messenger.properties 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/messenger.properties 2022-04-15 07:51:52.000000000 +0000 @@ -330,7 +330,7 @@ # #1 is the number of origins remoteAllowAll=Αποδοχή απομακρυσμένου περιεχομένου από την #1 πηγή που εμφανίζεται παραπάνω;Αποδοχή απομακρυσμένου περιεχομένου και από τις #1 πηγές που εμφανίζονται παραπάνω -phishingBarMessage=Το μήνυμα μπορεί να αποτελεί απάτη. +phishingBarMessage=Αυτό το μήνυμα μπορεί να αποτελεί απάτη. phishingBarPrefLabel=Επιλογές phishingBarPrefAccesskey=Ε phishingBarPrefLabelUnix=Προτιμήσεις @@ -665,7 +665,7 @@ # order to help them confirm they picked what they thought they picked. This # is the case in which we apply the columns only to the folder and not to any of # its children. -threadPane.columnPicker.confirmFolder.noChildren.message=Εφαρμογή στηλών τρέχοντος φακέλου στο %S; +threadPane.columnPicker.confirmFolder.noChildren.message=Εφαρμογή στηλών τρέχοντος φακέλου στο «%S»; # LOCALIZATION NOTE (threadPane.columnPicker.confirmFolder.withChildren.title): # When the user selects a folder to apply the currently displayed columns to via @@ -682,7 +682,7 @@ # selected in order to help them confirm they picked what they thought they # picked. This is the case in which we apply the columns to the folder and all # of its children. -threadPane.columnPicker.confirmFolder.withChildren.message=Εφαρμογή στηλών τρέχοντος φακέλου στο %S και τους υποφακέλους του; +threadPane.columnPicker.confirmFolder.withChildren.message=Εφαρμογή στηλών τρέχοντος φακέλου στο «%S» και τους υποφακέλους του; # LOCALIZATION NOTE (lwthemeInstallRequest.message): %S will be replaced with # the host name of the site. diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/virtualFolderProperties.dtd thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/virtualFolderProperties.dtd --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger/virtualFolderProperties.dtd 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger/virtualFolderProperties.dtd 2022-04-15 07:51:52.000000000 +0000 @@ -2,7 +2,7 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - + diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger-newsblog/feed-subscriptions.dtd thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger-newsblog/feed-subscriptions.dtd --- thunderbird-91.7.0+build2/l10n/el/mail/chrome/messenger-newsblog/feed-subscriptions.dtd 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/chrome/messenger-newsblog/feed-subscriptions.dtd 2022-04-15 07:51:52.000000000 +0000 @@ -25,9 +25,9 @@ - + - + diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/aboutDialog.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Τι νέο υπάρχει diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/aboutImport.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/aboutImport.ftl 2022-04-15 07:51:53.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Επιλέξτε για εισαγωγή Λογαριασμών, Βιβλίων διευθύνσεων, Ημερολογίων και άλλων δεδομένων από: import-address-book = Εισαγωγή αρχείου ευρετηρίου import-calendar = Εισαγωγή αρχείου ημερολογίου +export-profile = Εξαγωγή ## Buttons button-cancel = Ακύρωση button-back = Πίσω button-continue = Συνέχεια +button-export = Εξαγωγή ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Εισαγωγή από { $app } @@ -26,17 +33,52 @@ profile-file-picker-dir = Επιλέξτε ένα φάκελο προφίλ profile-file-picker-zip = Επιλέξτε ένα αρχείο zip (μικρότερο από 2 GB) items-pane-title = Επιλέξτε τι θα εισαγάγετε -items-pane-desc = Εισαγωγή από +items-pane-source = Τοποθεσία πηγής: items-pane-checkbox-accounts = Λογαριασμοί και ρυθμίσεις items-pane-checkbox-address-books = Ευρετήρια items-pane-checkbox-calendars = Ημερολόγια items-pane-checkbox-mail-messages = Μηνύματα email +## Import from address book file steps + +import-from-addr-book-file-desc = Επιλέξτε τον τύπο αρχείου που θέλετε να εισαγάγετε: +addr-book-csv-file = Αρχείο διαχωρισμένο με κόμμα ή καρτέλα (.csv, .tsv) +addr-book-ldif-file = Αρχείο LDIF (.ldif) +addr-book-vcard-file = Αρχείο vCard (.vcf, .vcard) +addr-book-sqlite-file = Αρχείο βάσης δεδομένων SQLite (.sqlite) +addr-book-mab-file = Αρχείο βάσης δεδομένων Mork (.mab) +addr-book-file-picker = Επιλογή αρχείου ευρετηρίου +addr-book-csv-field-map-title = Αντιστοίχιση ονομάτων πεδίων +addr-book-csv-field-map-desc = Επιλέξτε τα ευρετήρια που αντιστοιχούν στα πεδία πηγής. Καταργήστε την επιλογή των πεδίων που δεν θέλετε να εισαγάγετε. +addr-book-directories-pane-title = Επιλέξτε τον κατάλογο στον οποίο θέλετε να κάνετε εισαγωγή: +addr-book-directories-pane-source = Αρχείο πηγής: +addr-book-import-into-new-directory = Δημιουργία νέου καταλόγου + ## Import dialog progress-pane-title = Εισαγωγή +progress-pane-importing = Εισαγωγή +progress-pane-exporting = Εξαγωγή +progress-pane-finished-desc = Ολοκληρώθηκε. progress-pane-restart-desc = Κάντε επανεκκίνηση για να ολοκληρώσετε την εισαγωγή. error-pane-title = Σφάλμα error-message-zip-file-too-big = Το επιλεγμένο αρχείο zip είναι μεγαλύτερο από 2 GB. Παρακαλώ εξαγάγετέ το πρώτα και έπειτα, κάντε εισαγωγή από τον φάκελο εξαγωγής. error-message-extract-zip-file-failed = Αποτυχία εξαγωγής του αρχείου zip. Εξαγάγετέ το με μη αυτόματο τρόπο και στη συνέχεια πραγματοποιήστε εισαγωγή από τον φάκελο εξαγωγής. error-message-failed = Η εισαγωγή απέτυχε απροσδόκητα, περισσότερες πληροφορίες ενδέχεται να είναι διαθέσιμες στην Κονσόλα Σφαλμάτων. +error-export-failed = Απρόσμενη αποτυχία εξαγωγής, περισσότερες πληροφορίες θα βρείτε στην κονσόλα σφαλμάτων. + +## element + +csv-first-row-contains-headers = Η πρώτη σειρά περιέχει ονόματα πεδίων +csv-source-field = Πεδίο πηγής +csv-source-first-record = Πρώτη καταχώρηση +csv-source-second-record = Δεύτερη καταχώρηση +csv-target-field = Πεδίο ευρετηρίου διευθύνσεων + +## Export tab + +export-profile-desc = Εξαγάγετε λογαριασμούς αλληλογραφίας, μηνύματα email, ευρετήρια διευθύνσεων, ρυθμίσεις σε αρχείο zip. Όταν χρειαστεί, μπορείτε να εισαγάγετε το αρχείο .zip για να επαναφέρετε το προφίλ σας. +export-profile-desc2 = Εάν το τρέχον προφίλ σας είναι μεγαλύτερο από 2 GB, προτείνουμε να δημιουργήσετε χειροκίνητα αντίγραφα ασφαλείας. +export-open-profile-folder = Άνοιγμα φακέλου προφίλ +export-file-picker = Εξαγωγή σε αρχείο zip +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Νέο ευρετήριο διευθύνσεων CardDAV - +carddav-window-title = Νέο ευρετήριο διευθύνσεων CardDAV carddav-dialog = .buttonlabelaccept = Συνέχεια .buttonaccesskeyaccept = Σ - carddav-username-label = .value = Όνομα χρήστη: .accesskey = Ό - carddav-location-label = .value = Διεύθυνση: .accesskey = Δ carddav-location = .default-placeholder = URL ή όνομα υπολογιστή του διακομιστή ευρετηρίου - carddav-loading = Αναζήτηση ρυθμίσεων… carddav-known-incompatible = Το { $url } είναι γνωστό ότι δεν είναι συμβατό με το { -brand-short-name }. carddav-connection-error = Αποτυχία σύνδεσης. carddav-none-found = Δεν βρέθηκαν ευρετήρια διευθύνσεων για προσθήκη για το συγκεκριμένο λογαριασμό. carddav-already-added = Όλα τα ευρετήρια διευθύνσεων για το συγκεκριμένο λογαριασμό έχουν ήδη προστεθεί. - carddav-available-books = Διαθέσιμα ευρετήρια: diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -132,8 +132,8 @@ about-addressbook-details-home-address-header = Διεύθυνση οικίας about-addressbook-details-work-address-header = Διεύθυνση εργασίας about-addressbook-details-other-info-header = Άλλες πληροφορίες -about-addressbook-prompt-to-save-title = Αποθήκευση αλλαγών; -about-addressbook-prompt-to-save = Θέλετε να αποθηκεύσετε τις αλλαγές σας; +about-addressbook-unsaved-changes-prompt-title = Μη αποθηκευμένες αλλαγές +about-addressbook-unsaved-changes-prompt = Θέλετε να αποθηκεύσετε τις αλλαγές σας πριν αποχωρήσετε από την προβολή επεξεργασίας; # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/menubar.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/menubar.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -67,6 +67,9 @@ mail-uidensity-touch = .label = Αφή .accesskey = Α +menu-spaces-toolbar-button = + .label = Γραμμή χώρων + .accesskey = χ ## File diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:51:53.000000000 +0000 @@ -84,6 +84,12 @@ .tooltiptext = Εμφάνιση του πίνακα συνημμένων ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Απόκρυψη του πίνακα συνημμένων ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } συνημμένο + *[other] { $count } συνημμένα + } attachment-area-show = .title = Εμφάνιση πίνακα συνημμένων ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -239,8 +245,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Κατάργηση μορφοποίησης κειμένου -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Μεταφορτώθηκε σε άγνωστο λογαριασμό FileLink. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } - Συνημμένο FileLink +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = Το αρχείο «{ $filename }» επισυνάφθηκε ως FileLink. Μπορείτε να κάνετε λήψη του από τον παρακάτω σύνδεσμο. # Template @@ -253,22 +272,27 @@ *[other] Έχω συνδέσει { $count } αρχεία σε αυτό το email: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Μάθετε περισσότερα σχετικά με το { $lastLink }. - *[other] Μάθετε περισσότερα σχετικά με το { $firstLinks } και το { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Μάθετε περισσότερα σχετικά με το { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Μάθετε περισσότερα σχετικά με το { $firstLinks } και το { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Σύνδεσμος με κωδικό πρόσβασης # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = Υπηρεσία CloudFile: +cloud-file-template-service-name = Υπηρεσία FileLink: cloud-file-template-size = Μέγεθος: cloud-file-template-link = Σύνδεσμος: cloud-file-template-password-protected-link = Σύνδεσμος με κωδικό πρόσβασης: @@ -278,6 +302,9 @@ # Messages # $provider (string) - name of the online storage service that reported the error +cloud-file-connection-error-title = Σφάλμα σύνδεσης +cloud-file-connection-error = Το { -brand-short-name } είναι εκτός σύνδεσης. Δεν ήταν δυνατή η σύνδεση στο { $provider }. +# $provider (string) - name of the online storage service that reported the error # $filename (string) - name of the file that was uploaded and caused the error cloud-file-upload-error-with-custom-message-title = Το ανέβασμα του { $filename } στο { $provider } απέτυχε # $provider (string) - name of the online storage service that reported the error @@ -289,3 +316,9 @@ cloud-file-rename-error-with-custom-message-title = Η μετονομασία του { $filename } στο { $provider } απέτυχε # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = Το { $provider } δεν υποστηρίζει τη μετονομασία των ήδη ανεβασμένων αρχείων. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Σφάλμα συνημμένου FileLink +cloud-file-attachment-error = Αποτυχία ενημέρωσης του συνημμένου «{ $filename }» στο FileLink, επειδή το τοπικό του αρχείο έχει μετακινηθεί ή διαγραφεί. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Σφάλμα λογαριασμού FileLink +cloud-file-account-error = Αποτυχία ενημέρωσης του συνημμένου «{ $filename }» στο FileLink, επειδή ο λογαριασμός FileLink του έχει διαγραφεί. diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/messenger.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/messenger.ftl 2022-04-15 07:51:53.000000000 +0000 @@ -49,7 +49,7 @@ .toolbarname = Γραμμή περιοχής φακέλων .accesskey = Γ folder-pane-toolbar-options-button = - .tooltiptext = Επιλογές προβολής φακέλων + .tooltiptext = Επιλογές περιοχής φακέλων folder-pane-header-label = Φάκελοι ## Folder Toolbar Header Popup @@ -169,3 +169,81 @@ ## error messages decrypt-and-copy-failures = Δεν ήταν δυνατή η αποκρυπτογράφηση και αντιγραφή { $failures } από { $total } μηνύματα. + +## Spaces toolbar + +spaces-toolbar = + .toolbarname = Γραμμή χώρων +spaces-toolbar-button-mail = + .title = Μετάβαση στην καρτέλα αλληλογραφίας +spaces-toolbar-button-address-book = + .title = Εναλλαγή στην καρτέλα ευρετηρίων +spaces-toolbar-button-calendar = + .title = Εναλλαγή στην καρτέλα ημερολογίου +spaces-toolbar-button-tasks = + .title = Εναλλαγή στην καρτέλα εργασιών +spaces-toolbar-button-chat = + .title = Εναλλαγή στην καρτέλα συνομιλίας +spaces-toolbar-button-settings = + .title = Εναλλαγή στην καρτέλα ρυθμίσεων +spaces-toolbar-button-collapse = + .title = Σύμπτυξη γραμμής χώρων +spaces-toolbar-button-reveal = + .title = Εμφάνιση γραμμής χώρων +spaces-context-new-tab-item = + .label = Άνοιγμα σε νέα καρτέλα +spaces-context-new-window-item = + .label = Άνοιγμα σε νέο παράθυρο +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Εναλλαγή σε { $tabName } +settings-context-open-settings-item = + .label = Άνοιγμα ρυθμίσεων +settings-context-open-account-settings-item = + .label = Άνοιγμα ρυθμίσεων λογαριασμού +settings-context-open-addons-item = + .label = Άνοιγμα προσθέτων και θεμάτων + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Άνοιγμα μενού χώρων +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [one] Ένα μη αναγνωσμένο μήνυμα + *[other] { $count } μη αναγνωσμένα μηνύματα + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Προσαρμογή… +spaces-customize-panel-title = Ρυθμίσεις γραμμής χώρων +spaces-customize-background-color = Χρώμα φόντου +spaces-customize-icon-color = Χρώμα κουμπιού +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Επιλεγμένο χρώμα φόντου κουμπιού +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Επιλεγμένο χρώμα κουμπιού +spaces-customize-button-restore = Επαναφορά προεπιλογών + .accesskey = φ +spaces-customize-button-save = Τέλος + .accesskey = Τ diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -16,15 +16,13 @@ .label = Άνοιγμα λεπτομερειών και επεξεργασία της αποδοχής… openpgp-one-recipient-status-discover = .label = Ανακαλύψτε νέα ή ενημερωμένα κλειδιά - openpgp-one-recipient-status-instruction1 = Για να στείλετε ένα κρυπτογραφημένο μήνυμα από άκρο σε άκρο σε έναν παραλήπτη, πρέπει να αποκτήσετε το δημόσιο κλειδί τους OpenPGP και να το ορίσετε ως αποδεκτό. openpgp-one-recipient-status-instruction2 = Για να αποκτήσετε το δημόσιο κλειδί τους, εισαγάγετέ το από ένα μήνυμα ηλεκτρονικού ταχυδρομείου που σας έστειλαν και το περιέχει. Εναλλακτικά, μπορείτε να προσπαθήσετε να ψάξετε για το δημόσιο κλειδί τους σε έναν κατάλογο. - openpgp-key-own = Αποδεκτό (προσωπικό κλειδί) openpgp-key-secret-not-personal = Μη χρησιμοποιήσιμο openpgp-key-verified = Αποδεκτό (επαληθευμένο) openpgp-key-unverified = Αποδεκτό (μη επαληθευμένο) openpgp-key-undecided = Μη αποδεκτό (χωρίς απόφαση) openpgp-key-rejected = Μη αποδεκτό (απορριπτέο) - +openpgp-key-expired = Έληξε openpgp-intro = Διαθέσιμα δημόσια κλειδιά για { $key } diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/otr/add-finger.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/otr/add-finger.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Προσθήκη αποτυπώματος κλειδιού OTR - +otr-add-finger-title = Προσθήκη αποτυπώματος κλειδιού OTR # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Εισαγάγετε το αποτύπωμα κλειδιού OTR για το { $name }. - otr-add-finger-fingerprint = Δακτυλικό αποτύπωμα: otr-add-finger-tooltip-error = Καταχωρίστηκε μη έγκυρος χαρακτήρας. Επιτρέπονται μόνο τα γράμματα ABCDEF και αριθμοί - otr-add-finger-input = .placeholder = Το αποτύπωμα κλειδιού OTR μήκους 40 χαρακτήρων diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/otr/finger.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/otr/finger.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Κλείσιμο .title = Προηγούμενα αποτυπώματα OTR - +otr-finger-title = Προηγούμενα αποτυπώματα OTR finger-intro = Αποτυπώματα κλειδιού OTR από προηγούμενες συζητήσεις με διατερματική κρυπτογράφηση. - finger-screen-name = .label = Επαφή finger-verified = .label = Κατάσταση επαλήθευσης finger-fingerprint = .label = Αποτύπωμα - finger-remove = .label = Αφαίρεση επιλεγμένων - finger-remove-all = .label = Αφαίρεση όλων diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/preferences/preferences.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -127,7 +127,7 @@ adding-opensearch-provider-failed-title = Αποτυχία προσθήκης παρόχου OpenSearch adding-opensearch-provider-failed-text = Δεν ήταν δυνατή η προσθήκη παρόχου OpenSearch για το { $url }. minimize-to-tray-label = - .label = Όταν το { -brand-short-name } ελαχιστοποιείται, να γίνεται μετακίνηση στη γραμμή εργασιών + .label = Όταν το { -brand-short-name } ελαχιστοποιείται, να γίνεται μετακίνηση στην περιοχή ειδοποιήσεων .accesskey = ε new-message-arrival = Όταν φθάνουν νέα μηνύματα: mail-play-sound-label = @@ -155,7 +155,7 @@ biff-use-system-alert = .label = Χρήση ειδοποιήσεων συστήματος tray-icon-unread-label = - .label = Εμφάνιση εικονιδίου για μη αναγνωσμένα μηνύματα στη γραμμή εργασίων + .label = Εμφάνιση εικονιδίου για μη αναγνωσμένα μηνύματα στην περιοχή ειδοποιήσεων .accesskey = φ tray-icon-unread-description = Προτείνεται εάν χρησιμοποιείτε μικρά κουμπιά στη γραμμή εργασιών mail-system-sound-label = @@ -168,7 +168,7 @@ .label = Περιήγηση… .accesskey = γ enable-gloda-search-label = - .label = Ενεργοποίηση καθολικής αναζήτησης και ευρετηριοποίησης + .label = Ενεργοποίηση καθολικής αναζήτησης και ευρετηρίασης .accesskey = γ datetime-formatting-legend = Μορφή ημερομηνίας και ώρας language-selector-legend = Γλώσσα @@ -189,6 +189,9 @@ smooth-scrolling-label = .label = Χρήση ομαλής κύλισης .accesskey = ο +browsing-gtk-use-non-overlay-scrollbars = + .label = Πάντα εμφάνιση γραμμών κύλισης + .accesskey = φ system-integration-legend = Ενσωμάτωση συστήματος always-check-default = .label = Να γίνεται πάντα έλεγχος στην εκκίνηση για το αν το { -brand-short-name } είναι το προεπιλεγμένο πρόγραμμα αλληλογραφίας @@ -229,7 +232,7 @@ .label = Εμφάνιση ιστορικού ενημερώσεων .accesskey = ι use-service = - .label = Χρήση μιας υπηρεσίας παρασκηνίου για την εγκατάσταση ενημερώσεων + .label = Χρήση υπηρεσίας παρασκηνίου για την εγκατάσταση ενημερώσεων .accesskey = υ cross-user-udpate-warning = Αυτή η ρύθμιση θα εφαρμοστεί σε όλους τους λογαριασμούς των Windows και τα προφίλ του { -brand-short-name } με αυτή την εγκατάσταση του { -brand-short-name }. networking-legend = Σύνδεση @@ -576,7 +579,7 @@ .label = Ερώτηση κάθε φορά .accesskey = Ε ocsp-label = - .label = Ερώτηση στους διακομιστές OCSP για την επιβεβαίωση της τρέχουσας εγκυρότητας των πιστοποιητικών + .label = Αίτημα σε διακομιστές OCSP για την επιβεβαίωση της τρέχουσας εγκυρότητας των πιστοποιητικών .accesskey = δ certificate-button = .label = Διαχείριση πιστοποιητικών… diff -Nru thunderbird-91.7.0+build2/l10n/el/mail/messenger/preferences/receipts.ftl thunderbird-91.8.1+build1/l10n/el/mail/messenger/preferences/receipts.ftl --- thunderbird-91.7.0+build2/l10n/el/mail/messenger/preferences/receipts.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/mail/messenger/preferences/receipts.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -4,19 +4,10 @@ receipts-dialog-window = .title = Αποδεικτικά προβολής -return-receipt-checkbox = - .label = Κατά την αποστολή μηνυμάτων, να ζητείται πάντα αποδεικτικό προβολής - .accesskey = Κ return-receipt-checkbox-control = .label = Κατά την αποστολή μηνυμάτων, να ζητείται πάντα αποδεικτικό προβολής .accesskey = Κ -receipt-arrive-label = Μετά την επιστροφή μιας βεβαίωσης -receipt-leave-radio = - .label = Διατήρηση στα εισερχόμενα - .accesskey = τ -receipt-move-radio = - .label = Μεταφορά στον φάκελο «Απεσταλμένα» - .accesskey = μ +receipt-arrive-label = Όταν φτάνει ένα αποδεικτικό: receipt-leave-radio-control = .label = Διατήρηση στα εισερχόμενα .accesskey = ρ @@ -24,15 +15,6 @@ .label = Μετακίνηση στον φάκελο «Απεσταλμένα» .accesskey = φ receipt-request-label = Κατά τη λήψη αιτήματος για αποδεικτικό προβολής: -receipt-return-never-radio = - .label = Να μην γίνεται ποτέ αποστολή αποδεικτικού προβολής - .accesskey = ν -receipt-return-some-radio = - .label = Αποδοχή αποδεικτικών προβολής για ορισμένα μηνύματα - .accesskey = π -receipt-not-to-cc = - .value = Αν δεν είμαι στα πεδία «Προς» ή «Κοιν.» του μηνύματος: - .accesskey = ν receipt-return-never-radio-control = .label = Να μην γίνεται ποτέ αποστολή αποδεικτικού προβολής .accesskey = ν @@ -48,12 +30,6 @@ .label = Αποστολή πάντα receipt-send-ask-label = .label = Ερώτηση -sender-outside-domain = - .value = Αν ο αποστολέας είναι εκτός του τομέα μου: - .accesskey = κ -other-cases-label = - .value = Σε όλες τις άλλες περιπτώσεις: - .accesskey = λ sender-outside-domain-label = .value = Αν ο αποστολέας είναι εκτός του τομέα μου: .accesskey = μ diff -Nru thunderbird-91.7.0+build2/l10n/el/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/el/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/el/netwerk/necko.properties 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/netwerk/necko.properties 2022-04-15 07:51:52.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Το cookie “%1$S” έχει απορριφθεί επειδή έχει ήδη λήξει. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Το cookie «%1$S» έχει απορριφθεί επειδή είναι σε συγκείμενο μεταξύ ιστοτόπων και το «SameSite» του είναι «Lax» ή «Strict». + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Προειδοποίηση: το «%1$S» είναι παρωχημένο, παρακαλώ χρησιμοποιήστε το «%2$S» diff -Nru thunderbird-91.7.0+build2/l10n/el/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/el/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/el/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:51:52.000000000 +0000 @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Ανοιχτόχρωμο σύνολο χρωμάτων aboutReader.toolbar.colorschemedark = Σκουρόχρωμο σύνολο χρωμάτων aboutReader.toolbar.colorschemesepia = Σέπια σύνολο χρωμάτων +aboutReader.toolbar.colorschemeauto = Αυτόματο σύνολο χρωμάτων diff -Nru thunderbird-91.7.0+build2/l10n/el/toolkit/chrome/global/aboutStudies.properties thunderbird-91.8.1+build1/l10n/el/toolkit/chrome/global/aboutStudies.properties --- thunderbird-91.7.0+build2/l10n/el/toolkit/chrome/global/aboutStudies.properties 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/toolkit/chrome/global/aboutStudies.properties 2022-04-15 07:51:52.000000000 +0000 @@ -17,8 +17,8 @@ # LOCALIZATION NOTE (completeStatus): Displayed for a study that is already complete completeStatus = Ολόκληρο -updateButtonWin = Επιλογές ενημερώσεων -updateButtonUnix = Προτιμήσεις ενημερώσεων +updateButtonWin = Ενημέρωση επιλογών +updateButtonUnix = Ενημέρωση προτιμήσεων learnMore = Μάθετε περισσότερα noStudies = Δεν έχετε λάβει μέρος σε καμία μελέτη. disabledList = Αυτή είναι μια λίστα με τις μελέτες που έχετε συμμετάσχει. Δεν θα γίνουν νέες μελέτες. diff -Nru thunderbird-91.7.0+build2/l10n/el/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/el/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/el/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/toolkit/chrome/global/narrate.properties 2022-04-15 07:51:52.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Ακρόαση back = Πίσω start = Έναρξη stop = Διακοπή +# %S is the keyboard shortcut for the start command +start-label = Έναρξη (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Διακοπή (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = Α forward = Προώθηση speed = Ταχύτητα selectvoicelabel = Φωνή: diff -Nru thunderbird-91.7.0+build2/l10n/el/toolkit/crashreporter/crashreporter.ini thunderbird-91.8.1+build1/l10n/el/toolkit/crashreporter/crashreporter.ini --- thunderbird-91.7.0+build2/l10n/el/toolkit/crashreporter/crashreporter.ini 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/toolkit/crashreporter/crashreporter.ini 2022-04-15 07:51:52.000000000 +0000 @@ -25,10 +25,8 @@ CommentGrayText=Προσθήκη σχολίου (τα σχόλια είναι ορατά δημόσια) ExtraReportInfo=Αυτή η αναφορά περιέχει ακόμα πληροφορίες για την κατάσταση της εφαρμογής την στιγμή που κόλλησε. # LOCALIZATION NOTE (CheckSendReport): The %s is replaced with the vendor name. -CheckSendReport=Ενημερώστε τη %s σχετικά με αυτή την κατάρρευση, ώστε να διορθωθεί -CheckIncludeURL=Να συμπεριληφθεί και η διεύθυνση της τελευταίας σελίδας -CheckAllowEmail=Να επιτρέπεται στον %s να έρθει σε επαφή μαζί μου για αυτή την αναφορά -EmailGrayText=Εισάγετε εδώ την διεύθυνση email σας +CheckSendReport=Αποστολή πληροφοριών σχετικά με αυτήν την κατάρρευση στη %s, ώστε να διορθωθεί +CheckIncludeURL=Να συμπεριληφθεί η διεύθυνση της σελίδας που βρισκόμουν ReportPreSubmit2=Η αναφορά κατάρρευσης θα υποβληθεί πριν από την επανεκκίνηση ή το κλείσιμο της εφαρμογής. ReportDuringSubmit2=Υποβολή της αναφοράς σας… ReportSubmitSuccess=Η αναφορά υποβλήθηκε επιτυχώς! diff -Nru thunderbird-91.7.0+build2/l10n/el/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/el/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/el/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } καρέ + *[other] { $frames } καρέ + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } κανάλι + *[other] { $channels } κανάλια + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/el/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/el/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/el/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Γραμμή διευθύνσεων: εμφάνιση αποτελεσμάτων κατά τη σύνταξη IME experimental-features-ime-search-description = Το IME (Input Method Editor) είναι ένα εργαλείο που σας επιτρέπει να εισαγάγετε περίπλοκα σύμβολα, όπως αυτά που χρησιμοποιούνται στις γλώσσες της Ανατολικής Ασίας ή της Ινδίας, με ένα τυπικό πληκτρολόγιο. Η ενεργοποίηση αυτού του πειράματος θα διατηρεί ανοικτή τη λίστα της γραμμής διευθύνσεων, εμφανίζοντας αποτελέσματα και προτάσεις αναζήτησης, κατά τη χρήση του IME για εισαγωγή κειμένου. Σημειώστε ότι το IME ενδέχεται να εμφανίσει ένα παράθυρο που καλύπτει τα αποτελέσματα της γραμμής διευθύνσεων, επομένως αυτή η προτίμηση προτείνεται μόνο για IME που δεν χρησιμοποιεί αυτό τον τύπο παραθύρου. +# Firefox 100 +experimental-features-firefox-100 = + .label = Αλφαριθμητικό πράκτορα χρήστη του { -brand-product-name } 100 +experimental-features-firefox-100-description = Το { -brand-short-name } στέλνει σε ιστοτόπους μια συμβολοσειρά πράκτορα χρήστη για την έκδοση 100 του { -brand-product-name }. Χρησιμοποιήστε αυτήν τη ρύθμιση για να δείτε εάν οι ιστότοποι θα δυσλειτουργούν όταν το { -brand-short-name } φτάσει σε τριψήφιο αριθμό έκδοσης. Το πραγματικό { -brand-product-name } 100 πρόκειται να κυκλοφορήσει τον Μάιο του 2022, οπότε αρχίστε να δοκιμάζετε τους ιστοτόπους σας τώρα! diff -Nru thunderbird-91.7.0+build2/l10n/el/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/el/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/el/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:37:08.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/el/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:51:52.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Υποδοχή # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Παράγων IPC σε sandbox ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/en-CA/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Privacy: Private Event calendar-editable-item-privacy-icon-confidential = .alt = Privacy: Show Time and Date Only +calendar-editable-item-recurrence = + .alt = Recurring +calendar-editable-item-recurrence-exception = + .alt = Recurrence exception calendar-editable-item-todo-icon-task = .alt = Task calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/chat/matrix.properties thunderbird-91.8.1+build1/l10n/en-CA/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/en-CA/chat/matrix.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/chat/matrix.properties 2022-04-15 07:52:00.000000000 +0000 @@ -146,10 +146,15 @@ # %S is the reason string for the particular action. # Used within context of ban, kick and withdrew invite. message.reason=Reason: %S. -# Gets message.reason appended, if a reason was specified. + +# LOCALIZATION NOTE (message.*): +# These are shown as system messages in the conversation. # %1$S is the name of the user who banned. # %2$S is the name of the user who got banned. message.banned=%1$S banned %2$S. +# Same as message.banned but with a reason. +# %3$S is the reason the user was banned. +message.bannedWithReason=%1$S banned %2$S. Reason: %3$S # %1$S is the name of the user who accepted the invitation. # %2$S is the name of the user who sent the invitation. message.acceptedInviteFor=%1$S accepted the invitation for %2$S. @@ -177,14 +182,18 @@ # %1$S is the name of the user who unbanned. # %2$S is the name of the user who got unbanned. message.unbanned=%1$S unbanned %2$S. -# Gets message.reason appended, if a reason was specified. # %1$S is the name of the user who kicked. # %2$S is the name of the user who got kicked. message.kicked=%1$S kicked %2$S. -# Gets message.reason appended, if a reason was specified. +# Same as message.kicked but with a third parameter for the reason. +# %3$S is the reason for the kick. +message.kickedWithReason=%1$S kicked %2$S. Reason: %3$S # %1$S is the name of the user who withdrew invitation. # %2$S is the name of the user whose invitation has been withdrawn. message.withdrewInvite=%1$S withdrew %2$S's invitation. +# Same as message.withdrewInvite but with a third paramter for the reason. +# %3$S is the reason the invite was withdrawn. +message.withdrewInviteWithReason=%1$S withdrew %2$S's invitation. Reason: %3$S # %S is the name of the user who has removed the room name. message.roomName.remove=%S removed the room name. # %1$S is the name of the user who changed the room name. @@ -233,3 +242,11 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S cancelled the verification with the reason: %2$S message.verification.done=Verification completed. +message.decryptionError=Could not decrypt the contents of this message. To request encryption keys from your other devices, right click this message. +message.decrypting=Decrypting… +message.redacted=Message was redacted. + +# Label in the message context menu +message.action.requestKey=Re-request Keys +message.action.redact=Redact +message.action.report=Report Message diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/compatibility.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/compatibility.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (experimental) compatibility-issue-prefixneeded = (prefix needed) compatibility-issue-deprecated-experimental = (deprecated, experimental) - compatibility-issue-deprecated-prefixneeded = (deprecated, prefix needed) compatibility-issue-experimental-prefixneeded = (experimental, prefix needed) compatibility-issue-deprecated-experimental-prefixneeded = (deprecated, experimental, prefix needed) @@ -43,7 +42,14 @@ [one] { $number } occurrence *[other] { $number } occurrences } - compatibility-no-issues-found = No compatibility issues found. compatibility-close-settings-button = .title = Close settings +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Compatibility issues in: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/debugger.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/debugger.properties 2022-04-15 07:51:59.000000000 +0000 @@ -642,6 +642,26 @@ ignoreContextItem.unignore=Unignore source ignoreContextItem.unignore.accesskey=U +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Ignore line +ignoreContextItem.ignoreLine.accesskey=l + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Unignore line +ignoreContextItem.unignoreLine.accesskey=n + +# LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated +# with the ignore lines context menu item +ignoreContextItem.ignoreLines=Ignore lines +ignoreContextItem.ignoreLines.accesskey=i + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLines): Text associated +# with the unignore lines context menu item +ignoreContextItem.unignoreLines=Unignore lines +ignoreContextItem.unignoreLines.accesskey=u + # LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated # with a mapped source. %S is replaced by the source map origin. sourceFooter.mappedSource=(From %S) diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/netmonitor.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/netmonitor.properties 2022-04-15 07:51:59.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=The string “%S” was removed from the beginning of the JSON shown below + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -855,6 +860,10 @@ # in the action bar's search tab netmonitor.actionbar.search=Search +# LOCALIZATION NOTE (netmonitor.actionbar.HTTPCustomRequest): This is the label displayed +# in the action bar's edit and resend tab +netmonitor.actionbar.HTTPCustomRequest=New Request + # LOCALIZATION NOTE (messagesTruncated): This is the text displayed # in the messages panel when the number of messages is over the # truncation limit. @@ -1005,6 +1014,10 @@ # in the network toolbar for the search button. netmonitor.toolbar.search=Search +# LOCALIZATION NOTE (netmonitor.toolbar.HTTPCustomRequest): This is the tooltip label displayed +# in the network toolbar for the new HTTP Custom Request button. +netmonitor.toolbar.HTTPCustomRequest=New Request + # LOCALIZATION NOTE (netmonitor.toolbar.resetColumns): This is the label # displayed in the network table header context menu. netmonitor.toolbar.resetColumns=Reset Columns @@ -1452,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Query String +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL Parameters + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Request Headers +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Headers + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=name + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=value + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Body + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=payload + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Request Body @@ -1468,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Cancel +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Clear + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Remove item + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Back diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/toolbox.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/toolbox.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Disable Popup Auto-Hide +toolbox-meatball-menu-pseudo-locale-accented = Enable “accented” locale +toolbox-meatball-menu-pseudo-locale-bidi = Enable “bidi” locale ## diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/devtools/client/toolbox-options.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/devtools/client/toolbox-options.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -10,19 +10,15 @@ # The heading options-select-default-tools-label = Default Developer Tools - # The label for the explanation of the * marker on a tool which is currently not supported # for the target of the toolbox. options-tool-not-supported-label = * Not supported for current toolbox target - # The label for the heading of group of checkboxes corresponding to the developer tools # added by add-ons. This heading is hidden when there is no developer tool installed by add-ons. options-select-additional-tools-label = Developer Tools installed by add-ons - # The label for the heading of group of checkboxes corresponding to the default developer # tool buttons. options-select-enabled-toolbox-buttons-label = Available Toolbox Buttons - # The label for the heading of the radiobox corresponding to the theme options-select-dev-tools-theme-label = Themes @@ -30,12 +26,10 @@ # The heading options-context-inspector = Inspector - # The label for the checkbox option to show user agent styles options-show-user-agent-styles-label = Show Browser Styles options-show-user-agent-styles-tooltip = .title = Turning this on will show default styles that are loaded by the browser. - # The label for the checkbox option to enable collapse attributes options-collapse-attrs-label = Truncate DOM attributes options-collapse-attrs-tooltip = @@ -48,13 +42,13 @@ options-default-color-unit-hex = Hex options-default-color-unit-hsl = HSL(A) options-default-color-unit-rgb = RGB(A) +options-default-color-unit-hwb = HWB options-default-color-unit-name = Colour Names ## Style Editor section # The heading options-styleeditor-label = Style Editor - # The label for the checkbox that toggles autocompletion of css in the Style Editor options-stylesheet-autocompletion-label = Autocomplete CSS options-stylesheet-autocompletion-tooltip = @@ -64,12 +58,10 @@ # The heading options-screenshot-label = Screenshot Behaviour - # Label for the checkbox that toggles screenshot to clipboard feature options-screenshot-clipboard-only-label = Screenshot to clipboard only options-screenshot-clipboard-tooltip2 = .title = Saves the screenshot directly to the clipboard - # Label for the checkbox that toggles the camera shutter audio for screenshot tool options-screenshot-audio-label = Play camera shutter sound options-screenshot-audio-tooltip = @@ -79,7 +71,6 @@ # The heading options-sourceeditor-label = Editor Preferences - options-sourceeditor-detectindentation-tooltip = .title = Guess indentation based on source content options-sourceeditor-detectindentation-label = Detect indentation @@ -97,40 +88,36 @@ # The heading (this item is also used in perftools.ftl) options-context-advanced-settings = Advanced settings - # The label for the checkbox that toggles the HTTP cache on or off options-disable-http-cache-label = Disable HTTP Cache (when toolbox is open) options-disable-http-cache-tooltip = .title = Turning this option on will disable the HTTP cache for all tabs that have the toolbox open. Service Workers are not affected by this option. - # The label for checkbox that toggles JavaScript on or off options-disable-javascript-label = Disable JavaScript * options-disable-javascript-tooltip = .title = Turning this option on will disable JavaScript for the current tab. If the tab or the toolbox is closed then this setting will be forgotten. - # The label for checkbox that toggles chrome debugging, i.e. the devtools.chrome.enabled preference options-enable-chrome-label = Enable browser chrome and add-on debugging toolboxes options-enable-chrome-tooltip = .title = Turning this option on will allow you to use various developer tools in browser context (via Tools > Web Developer > Browser Toolbox) and debug add-ons from the Add-ons Manager - # The label for checkbox that toggles remote debugging, i.e. the devtools.debugger.remote-enabled preference options-enable-remote-label = Enable remote debugging options-enable-remote-tooltip2 = .title = Turning this option on will allow to debug this browser instance remotely - +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Enable custom formatters +options-enable-custom-formatters-tooltip = + .title = Turning this option on will allow sites to define custom formatters for DOM objects # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Enable Service Workers over HTTP (when toolbox is open) options-enable-service-workers-http-tooltip = .title = Turning this option on will enable the service workers over HTTP for all tabs that have the toolbox open. - # The label for the checkbox that toggles source maps in all tools. options-source-maps-label = Enable Source Maps options-source-maps-tooltip = .title = If you enable this option sources will be mapped in the tools. - # The message shown for settings that trigger page reload options-context-triggers-page-refresh = * Current session only, reloads the page - # The label for the checkbox that toggles the display of the platform data in the # Profiler i.e. devtools.profiler.ui.show-platform-data a boolean preference in about:config options-show-platform-data-label = Show Gecko platform data diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/en-CA/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/en-CA/dom/chrome/dom/dom.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/dom/chrome/dom/dom.properties 2022-04-15 07:52:00.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Please enter a URL. FormValidationInvalidDate=Please enter a valid date. FormValidationInvalidTime=Please enter a valid time. +FormValidationInvalidDateTime=Please enter valid date and time. +FormValidationInvalidDateMonth=Please enter a valid month. +FormValidationInvalidDateWeek=Please enter a valid week. FormValidationPatternMismatch=Please match the requested format. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Please match the requested format: %S. @@ -430,3 +433,8 @@ # LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". OffscreenCanvasToBlobWarning=OffscreenCanvas.toBlob() is deprecated. Use OffscreenCanvas.convertToBlob() instead. + +# LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" +IDBDatabaseCreateMutableFileWarning=IDBDatabase.createMutableFile() is deprecated. If this API gets standardized, it will likely do so under the Origin Private File System effort at https://bugzil.la/1748667. +# LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" +IDBMutableFileOpenWarning=IDBMutableFile.open() is deprecated. If this API gets standardized, it will likely do so under the Origin Private File System effort at https://bugzil.la/1748667. diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/en-CA/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/en-CA/mail/chrome/messenger/addons.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/chrome/messenger/addons.properties 2022-04-15 07:51:59.000000000 +0000 @@ -107,7 +107,6 @@ # %S is brandShortName webextPerms.experimentWarning=Malicious add-ons can steal your private information or compromise your computer. Only install this add-on if you trust the source. - webextPerms.headerWithPerms=Add %S? This extension will have permission to: webextPerms.headerUnsigned=Add %S? This extension is unverified. Malicious extensions can steal your private information or compromise your computer. Only add it if you trust the source. webextPerms.headerUnsignedWithPerms=Add %S? This extension is unverified. Malicious extensions can steal your private information or compromise your computer. Only add it if you trust the source. This extension will have permission to: @@ -226,6 +225,18 @@ # hosts for which this webextension is requesting permission. webextPerms.hostDescription.tooManySites=Access your data on #1 other site;Access your data on #1 other sites +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextSitePerms.headerWithPerms=Add %1$S? This extension grants the following capabilities to %2$S: +webextSitePerms.headerUnsignedWithPerms=Add %1$S? This extension is unverified. Malicious extensions can steal your private information or compromise your computer. Only add it if you trust the source. This extension grants the following capabilities to %2$S: + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties +webextSitePerms.description.midi=Access MIDI devices +webextSitePerms.description.midi-sysex=Access MIDI devices with SysEx support + # LOCALIZATION NOTE (webext.defaultSearch.description) # %1$S is replaced with the localized named of the extension that is asking to change the default search engine. # %2$S is replaced with the name of the current search engine @@ -235,4 +246,3 @@ webext.defaultSearchYes.accessKey=Y webext.defaultSearchNo.label=No webext.defaultSearchNo.accessKey=N - diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutDialog.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = What’s New diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutImport.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutImport.ftl 2022-04-15 07:52:00.000000000 +0000 @@ -0,0 +1,61 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +import-page-title = Import + +## Header + +import-from-app = Import from Application +import-from-app-desc = Choose to import Accounts, Address Books, Calendars, and other data from: +import-address-book = Import Address Book File +import-calendar = Import Calendar File + +## Buttons + +button-cancel = Cancel +button-back = Back +button-continue = Continue + +## Import from app steps + +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail +# Variables: +# $app (String) - The name of the app to import from +profiles-pane-title = Import from { $app } +profiles-pane-desc = Choose the location from which to import +profile-file-picker-dir = Select a profile folder +profile-file-picker-zip = Select a zip file (smaller than 2GB) +items-pane-title = Select what to import +items-pane-desc = Import from +items-pane-source = Source location: +items-pane-checkbox-accounts = Accounts and Settings +items-pane-checkbox-address-books = Address Books +items-pane-checkbox-calendars = Calendars +items-pane-checkbox-mail-messages = Mail Messages + +## Import from address book file steps + +import-from-addr-book-file-desc = Select the file type you would like to import: +addr-book-csv-file = Comma or tab separated file (.csv, .tsv) +addr-book-ldif-file = LDIF file (.ldif) +addr-book-vcard-file = vCard file (.vcf, .vcard) +addr-book-mab-file = Mork database file (.mab) +addr-book-file-picker = Select an address book file +addr-book-directories-pane-title = Select the directory you would like to import into: +addr-book-directories-pane-source = Source file: +addr-book-import-into-new-directory = Create a new directory + +## Import dialog + +progress-pane-title = Importing +progress-pane-finished-desc = Finished. +progress-pane-restart-desc = Restart to finish importing. +error-pane-title = Error +error-message-zip-file-too-big = The selected zip file is larger than 2GB. Please extract it first, then import from the extracted folder instead. +error-message-extract-zip-file-failed = Failed to extract the zip file. Please extract it manually, then import from the extracted folder instead. +error-message-failed = Import failed unexpectedly, more information may be available in the Error Console. diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutRights.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutRights.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutRights.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutRights.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -18,6 +18,15 @@ rights-intro-point-6 = In order to play back certain types of video content, { -brand-short-name } downloads certain content decryption modules from third parties. rights-webservices-header = { -brand-full-name } Web-Based Information Services rights-webservices = { -brand-full-name } uses web-based information services ("Services") to provide some of the features provided for your use with this binary version of { -brand-short-name } under the terms described below. If you do not want to use one or more of the Services or the terms below are unacceptable, you may disable the feature or Service(s). Instructions on how to disable a particular feature or Service may be found here. Other features and Services can be disabled in the application preferences. +rights-webservices2 = + { -brand-full-name } uses web-based information services (“Services”) to + provide some of the features provided for your use with this binary version + of { -brand-short-name } under the terms described below. If you do not + want to use one or more of the Services, or the terms below are + unacceptable, you may disable the feature or Service(s). Instructions on + how to disable a particular feature or Service may be found + here. Other features + and Services can be disabled in the application settings. rights-locationawarebrowsing = Location Aware Browsing: is always opt-in. No location information is ever sent without your permission. If you wish to disable the feature completely, follow these steps: rights-locationawarebrowsing-term-1 = In the URL bar, type about:config rights-locationawarebrowsing-term-2 = Type geo.enabled diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutSupportChat.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutSupportChat.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/aboutSupportChat.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/aboutSupportChat.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -0,0 +1,11 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +chat-title = Chat Accounts +chat-table-heading-account = ID +chat-table-heading-protocol = Protocol +chat-table-heading-name = Name +chat-table-heading-actions = Actions +chat-table-copy-debug-log = Copy Debug Log + .title = Copy errors and other logging from this chat account to the clipboard. May contain personal information like chat messages. diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/accountCentral.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/accountCentral.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/accountCentral.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/accountCentral.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -4,58 +4,44 @@ account-central-title = Welcome to { -brand-full-name } account-settings = Account Settings - # $accounts (Number) - the number of configured accounts setup-title = Choose What to Set Up about-title = About { -brand-full-name } resources-title = Resources - release-notes = .title = About { -brand-full-name } - email-label = Email .aria-label = Connect to your existing email account email-description = { -brand-short-name } lets you connect to your existing email account, to read your emails conveniently and efficiently from within the application. - calendar-label = Calendar .aria-label = Create a new calendar calendar-description = { -brand-short-name } lets you handle events and keeps you organized. Connecting to a remote calendar will keep all your events in sync across all your devices. - chat-label = Chat .aria-label = Connect to your chat account chat-description = { -brand-short-name } lets you connect to multiple instant messaging accounts, offering support for various platforms. - filelink-label = Filelink .aria-label = Set up Filelink filelink-description = { -brand-short-name } lets you set up a convenient Filelink cloud account to easily send large attachments. - addressbook-label = Address Book .aria-label = Create a new address book addressbook-description = { -brand-short-name } lets you organize all your contacts in an address book. You can also connect to a remote address book to keep all your contacts in sync. - feeds-label = Feeds .aria-label = Connect to feeds feeds-description = { -brand-short-name } lets you connect to RSS/Atom feeds to get news and updates from all around. - newsgroups-label = Newsgroups .aria-label = Connect to a newsgroup newsgroups-description = { -brand-short-name } lets you connect to all the newsgroups you want. - import-title = Import from Another Program import-paragraph = { -brand-short-name } lets you import mail messages, address book entries, feed subscriptions, preferences, and/or filters from other mail programs and common address book formats. - +import-paragraph2 = { -brand-short-name } lets you import mail messages, address book entries, feed subscriptions, settings, and/or filters from other mail programs and common address book formats. import-label = Import .aria-label = Import data from other programs - about-paragraph = Thunderbird is the leading open source, cross-platform email and calendaring client, free for business and personal use. We want it to stay secure and become even better. A donation will allow us to hire developers, pay for infrastructure, and continue to improve. - about-paragraph-consider-donation = Thunderbird is funded by users like you! If you like Thunderbird, please consider making a donation. The best way for you to ensure Thunderbird remains available is to make a donation. - explore-link = Explore Features support-link = Support involved-link = Get Involved developer-link = Developer Documentation - read = Read messages compose = Write a new message search = Search messages diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/accountManager.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/accountManager.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/accountManager.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/accountManager.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -3,6 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. open-preferences-sidebar-button = { -brand-short-name } Preferences +open-preferences-sidebar-button2 = { -brand-short-name } Settings open-addons-sidebar-button = Add-ons and Themes account-action-add-newsgroup-account = .label = Add Newsgroup Account… diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/accountProvisioner.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/accountProvisioner.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/accountProvisioner.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/accountProvisioner.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -51,3 +51,5 @@ account-provisioner-free-account = Free account-provision-price-per-year = { $price } a year account-provisioner-all-results-button = Show all results +account-provisioner-open-in-tab-img = + .title = Opens in a new Tab diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = New CardDAV Address Book - +carddav-window-title = New CardDAV Address Book carddav-dialog = .buttonlabelaccept = Continue .buttonaccesskeyaccept = C - carddav-username-label = .value = Username: .accesskey = U - carddav-location-label = .value = Location: .accesskey = L carddav-location = .default-placeholder = URL or host name of the address book server - carddav-loading = Looking up configuration… carddav-known-incompatible = { $url } is known to be incompatible with { -brand-short-name }. carddav-connection-error = Failed to connect. carddav-none-found = Found no address books to add for the specified account. carddav-already-added = All address books for the specified account have already been added. - carddav-available-books = Available address books: diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -132,5 +132,15 @@ about-addressbook-details-home-address-header = Home Address about-addressbook-details-work-address-header = Work Address about-addressbook-details-other-info-header = Other Information -about-addressbook-prompt-to-save-title = Save Changes? -about-addressbook-prompt-to-save = Do you want to save your changes? +about-addressbook-unsaved-changes-prompt-title = Unsaved Changes +about-addressbook-unsaved-changes-prompt = Do you want to save your changes before leaving the edit view? + +# Photo dialog + +about-addressbook-photo-drop-target = Drop or paste a photo here, or click to select a file. +about-addressbook-photo-drop-loading = Loading photo… +about-addressbook-photo-drop-error = Failed to load photo. +about-addressbook-photo-filepicker-title = Select an image file +about-addressbook-photo-discard = Discard existing photo +about-addressbook-photo-cancel = Cancel +about-addressbook-photo-save = Save diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/chat.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/chat.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/chat.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/chat.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -22,3 +22,18 @@ chat-buddy-identity-status = Encryption Trust chat-buddy-identity-status-verified = Verified chat-buddy-identity-status-unverified = Unverified + +## Conversation invite notification box + +# This string appears in a notification bar at the top of the Contacts window +# when someone invited the user to a multi user chat conversation, to request +# the user to confirm they want to join the chat. +# Variables: +# $conversation (String) - Name of the conversation the user is invited to. +chat-conv-invite-label = You have been invited to chat in { $conversation } +chat-conv-invite-accept = + .label = Accept + .accesskey = A +chat-conv-invite-deny = + .label = Reject + .accesskey = R diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/exportDialog.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/exportDialog.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/exportDialog.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/exportDialog.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -3,14 +3,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export-dialog-brand-name = { -brand-product-name } -export-dialog-window = - .title = Export export-dialog-title = Export export-dialog = .buttonlabelaccept = Next export-dialog-button-finish = Finish export-dialog-file-picker = Export to a zip file -export-dialog-desc1 = Export mail accounts, mail messages, address books, preferences to a zip file. +export-dialog-description1 = Export mail accounts, mail messages, address books, settings to a zip file. export-dialog-desc2 = When needed, you can import the zip file to restore your profile. export-dialog-exporting = Exporting… export-dialog-exported = Exported! diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/menubar.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/menubar.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -2,6 +2,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +toolbar-context-menu-menu-bar = + .toolbarname = Menu Bar + .accesskey = M ## Tools Menu @@ -10,6 +13,9 @@ menu-tools-preferences = .label = Preferences .accesskey = P +menu-tools-settings = + .label = Settings + .accesskey = e menu-addons-and-themes = .label = Add-ons and Themes .accesskey = A @@ -61,6 +67,9 @@ mail-uidensity-touch = .label = Touch .accesskey = T +menu-spaces-toolbar-button = + .label = Spaces Toolbar + .accesskey = S ## File diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:52:00.000000000 +0000 @@ -3,7 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Addressing widget +## Addressing widget # $type (String) - the type of the addressing row remove-address-row-button = @@ -43,7 +43,7 @@ .label = Expand List .accesskey = x -# Attachment widget +## Attachment widget ctrl-cmd-shift-pretty-prefix = { PLATFORM() -> @@ -86,6 +86,13 @@ .tooltiptext = Show the attachment pane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Hide the attachment pane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } Attachment + [one] { $count } Attachment + *[other] { $count } Attachments + } attachment-area-show = .title = Show the attachment pane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -101,7 +108,7 @@ *[other] Append Inline } -# Reorder Attachment Panel +## Reorder Attachment Panel move-attachment-first-panel-button = .label = Move First @@ -115,14 +122,14 @@ .label = Receipt .tooltiptext = Request a return receipt for this message -# Encryption +## Encryption message-to-be-signed-icon = .alt = Sign message message-to-be-encrypted-icon = .alt = Encrypt message -# Addressing Area +## Addressing Area to-compose-address-row-label = .value = To @@ -240,3 +247,62 @@ compose-tool-button-remove-text-styling = .tooltiptext = Remove Text Styling + +## FileLink + + +# Template + +# A line of text describing how many uploaded files have been appended to this +# message. Emphasis should be on sharing as opposed to attaching. This item is +# used as a header to a list, hence the colon. +cloud-file-count-header = + { $count -> + [one] I’ve linked { $count } file to this email: + *[other] I’ve linked { $count } files to this email: + } +# A text used in a footer, instructing the reader where to find additional +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Learn more about { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Learn more about { $firstLinks } and { $lastLink }. +# Tooltip for an icon, indicating that the link is protected by a password. +cloud-file-tooltip-password-protected-link = Password protected link +# Used in a list of stats about a specific file +# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Size - the size of the file (Size: 4.2 MB) +# Link - the link to the file (Link: https://some.provider.com) +# Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) +# Download Limit - stating the maximum allowed downloads, before the link becomes invalid +# (Download Limit: 6) +cloud-file-template-service = CloudFile Service: +cloud-file-template-size = Size: +cloud-file-template-link = Link: +cloud-file-template-password-protected-link = Password Protected Link: +cloud-file-template-expiry-date = Expiry Date: +cloud-file-template-download-limit = Download Limit: + +# Messages + +# $provider (string) - name of the online storage service that reported the error +cloud-file-connection-error-title = Connection Error +cloud-file-connection-error = { -brand-short-name } is offline. Could not connect to { $provider }. +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was uploaded and caused the error +cloud-file-upload-error-with-custom-message-title = Uploading { $filename } to { $provider } Failed +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-rename-error-title = Rename Error +cloud-file-rename-error = There was a problem renaming { $filename } on { $provider }. +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-rename-error-with-custom-message-title = Renaming { $filename } on { $provider } Failed +# $provider (string) - name of the online storage service that reported the error +cloud-file-rename-not-supported = { $provider } does not support renaming already uploaded files. diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/messenger.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/messenger.ftl 2022-04-15 07:52:00.000000000 +0000 @@ -2,6 +2,17 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +## Window controls + +messenger-window-minimize-button = + .tooltiptext = Minimize +messenger-window-maximize-button = + .tooltiptext = Maximize +messenger-window-restore-down-button = + .tooltiptext = Restore Down +messenger-window-close-button = + .tooltiptext = Close # Variables: # $count (Number) - Number of unread messages. unread-messages-os-tooltip = @@ -76,12 +87,14 @@ ## AppMenu -appmenu-save-as-file = - .label = File… # Since v89 we dropped the platforms distinction between Options or Preferences # and consolidated everything with Preferences. appmenu-preferences = .label = Preferences +appmenu-save-as-file = + .label = File… +appmenu-settings = + .label = Settings appmenu-addons-and-themes = .label = Add-ons and Themes appmenu-help-enter-troubleshoot-mode = @@ -97,11 +110,26 @@ context-menu-redirect-msg = .label = Redirect +mail-context-delete-messages = + .label = + { $count -> + [one] Delete message + *[other] Delete selected messages + } +context-menu-decrypt-to-folder = + .label = Copy As Decrypted To + .accesskey = y ## Message header pane other-action-redirect-msg = .label = Redirect +message-header-msg-flagged = + .title = Starred + .aria-label = Starred +message-header-msg-not-flagged = + .title = Not starred + .aria-label = Not starred ## Action Button Context Menu @@ -138,3 +166,59 @@ no-reply-title = Reply Not Supported no-reply-message = The reply address ({ $email }) does not appear to be a monitored address. Messages to this address will likely not be read by anyone. no-reply-reply-anyway-button = Reply Anyway + +## error messages + +decrypt-and-copy-failures = { $failures } of { $total } messages could not be decrypted and were not copied. + +## Spaces toolbar + +spaces-toolbar = + .toolbarname = Spaces Toolbar +spaces-toolbar-button-mail = + .title = Switch to the mail tab +spaces-toolbar-button-address-book = + .title = Switch to the address book tab +spaces-toolbar-button-calendar = + .title = Switch to the calendar tab +spaces-toolbar-button-tasks = + .title = Switch to the tasks tab +spaces-toolbar-button-chat = + .title = Switch to the chat tab +spaces-toolbar-button-settings = + .title = Switch to the settings tab +spaces-toolbar-button-collapse = + .title = Collapse spaces toolbar +spaces-toolbar-button-reveal = + .title = Show the spaces toolbar +spaces-context-new-tab-item = + .label = Open in new tab +spaces-context-new-window-item = + .label = Open in new window +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Switch to { $tabName } +settings-context-open-settings-item = + .label = Open Settings +settings-context-open-account-settings-item = + .label = Open Account Settings +settings-context-open-addons-item = + .label = Open Add-ons and Themes + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Open spaces menu +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/migration.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/migration.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/migration.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/migration.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -0,0 +1,15 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +migration-progress-header = Getting { -brand-short-name } ready… + +## Migration tasks + + +# These strings are displayed to the user if a migration is taking a long time. +# They should be short (no more than a handful of words) and in the present tense. + +migration-task-test-fast = Testing a fast change +migration-task-test-slow = Testing a slow change +migration-task-test-progress = Testing the progress bar diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/openpgp/msgReadStatus.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/openpgp/msgReadStatus.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/openpgp/msgReadStatus.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/openpgp/msgReadStatus.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -6,7 +6,6 @@ ## Message Header Encryption Button message-header-show-security-info-key = S - # $type (String) - the shortcut key defined in the message-header-show-security-info-key message-security-button = .title = @@ -14,18 +13,16 @@ [macos] Show Message Security (⌘ ⌥ { message-header-show-security-info-key }) *[other] Show Message Security (Ctrl+Alt+{ message-header-show-security-info-key }) } - openpgp-view-signer-key = .label = View signer key openpgp-view-your-encryption-key = .label = View your decryption key openpgp-openpgp = OpenPGP - openpgp-no-sig = No Digital Signature +openpgp-no-sig-info = This message does not include the sender’s digital signature. The absence of a digital signature means that the message could have been sent by someone pretending to have this email address. It is also possible that the message has been altered while in transit over the network. openpgp-uncertain-sig = Uncertain Digital Signature openpgp-invalid-sig = Invalid Digital Signature openpgp-good-sig = Good Digital Signature - openpgp-sig-uncertain-no-key = This message contains a digital signature, but it is uncertain if it is correct. To verify the signature, you need to obtain a copy of the sender’s public key. openpgp-sig-uncertain-uid-mismatch = This message contains a digital signature, but a mismatch was detected. The message was sent from an email address that doesn’t match the signer’s public key. openpgp-sig-uncertain-not-accepted = This message contains a digital signature, but you haven’t yet decided if the signer’s key is acceptable to you. @@ -34,23 +31,24 @@ openpgp-sig-valid-unverified = This message includes a valid digital signature from a key that you have already accepted. However, you have not yet verified that the key is really owned by the sender. openpgp-sig-valid-verified = This message includes a valid digital signature from a verified key. openpgp-sig-valid-own-key = This message includes a valid digital signature from your personal key. - openpgp-sig-key-id = Signer key ID: { $key } openpgp-sig-key-id-with-subkey-id = Signer key ID: { $key } (Sub key ID: { $subkey }) - openpgp-enc-key-id = Your decryption key ID: { $key } openpgp-enc-key-with-subkey-id = Your decryption key ID: { $key } (Sub key ID: { $subkey }) - +openpgp-enc-none = Message Is Not Encrypted +openpgp-enc-none-label = This message was not encrypted before it was sent. Information sent over the Internet without encryption can be seen by other people while in transit. +openpgp-enc-invalid-label = Message Cannot Be Decrypted +openpgp-enc-invalid = This message was encrypted before it was sent to you, but it cannot be decrypted. +openpgp-enc-clueless = There are unknown problems with this encrypted message. +openpgp-enc-valid-label = Message Is Encrypted +openpgp-enc-valid = This message was encrypted before it was sent to you. Encryption ensures the message can only be read by the recipients it was intended for. openpgp-unknown-key-id = Unknown key - openpgp-other-enc-additional-key-ids = In addition, the message was encrypted to the owners of the following keys: openpgp-other-enc-all-key-ids = The message was encrypted to the owners of the following keys: - openpgp-message-header-encrypted-ok-icon = .alt = Decryption successful openpgp-message-header-encrypted-notok-icon = .alt = Decryption failed - openpgp-message-header-signed-ok-icon = .alt = Good signature # Mismatch icon is used for notok state as well diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/otr/add-finger.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/otr/add-finger.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Add OTR Key Fingerprint - +otr-add-finger-title = Add OTR Key Fingerprint # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Enter the OTR key fingerprint for { $name }. - otr-add-finger-fingerprint = Fingerprint: otr-add-finger-tooltip-error = Invalid character entered. Only letters ABCDEF and numbers are allowed - otr-add-finger-input = .placeholder = The 40 characters long OTR key fingerprint diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/otr/finger.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/otr/finger.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Close .title = Previously Seen OTR Fingerprints - +otr-finger-title = Previously Seen OTR Fingerprints finger-intro = OTR key fingerprints from previous end-to-end encrypted conversations. - finger-screen-name = .label = Contact finger-verified = .label = Verification Status finger-fingerprint = .label = Fingerprint - finger-remove = .label = Remove Selected - finger-remove-all = .label = Remove All diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/otr/otrUI.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/otr/otrUI.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -6,86 +6,66 @@ refresh-label = Refresh the encrypted conversation auth-label = Verify your contact’s identity reauth-label = Reverify your contact’s identity - auth-cancel = Cancel auth-cancel-access-key = C - auth-error = An error occurred while verifying the identity of your contact. auth-success = Verifying your contact’s identity completed successfully. auth-success-them = Your contact has successfully verified your identity. You may want to verify their identity as well by asking your own question. auth-fail = Failed to verify the identity of your contact. auth-waiting = Waiting for the contact to complete the verification… - finger-verify = Verify finger-verify-access-key = V - +finger-ignore = Ignore +finger-ignore-access-key = I # Do not translate 'OTR' (name of an encryption protocol) buddycontextmenu-label = Add OTR Fingerprint - # Variables: # $name (String) - the screen name of a chat contact person alert-start = Attempting to start an encrypted conversation with { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-refresh = Attempting to refresh the encrypted conversation with { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-gone-insecure = The encrypted conversation with { $name } ended. - # Variables: # $name (String) - the screen name of a chat contact person finger-unseen = The identity of { $name } has not been verified yet. Casual eavesdropping is not possible, but with some effort someone could be listening in. Prevent surveillance by verifying this contact’s identity. - # Variables: # $name (String) - the screen name of a chat contact person finger-seen = { $name } is contacting you from an unrecognized computer. Casual eavesdropping is not possible, but with some effort someone could be listening in. Prevent surveillance by verifying this contact’s identity. - state-not-private = The current conversation is not private. - state-generic-not-private = The current conversation is not private. - # Variables: # $name (String) - the screen name of a chat contact person state-unverified = The current conversation is encrypted but not private, since the identity of { $name } has not yet been verified. - state-generic-unverified = The current conversation is encrypted but not private, since some identities have not yet been verified. - # Variables: # $name (String) - the screen name of a chat contact person state-private = The identity of { $name } has been verified. The current conversation is encrypted and private. - state-generic-private = The current conversation is encrypted and private. - # Variables: # $name (String) - the screen name of a chat contact person state-finished = { $name } has ended their encrypted conversation with you; you should do the same. - state-not-private-label = Insecure state-unverified-label = Unverified state-private-label = Private state-finished-label = Finished - # Variables: # $name (String) - the screen name of a chat contact person verify-request = { $name } requested the verification of your identity. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-private = You have verified the identity of { $name }. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-unverified = The identity of { $name } has not been verified. - verify-title = Verify your contact’s identity error-title = Error success-title = End to End Encryption success-them-title = Verify your contact’s identity fail-title = Unable to verify waiting-title = Verification request sent - # Do not translate 'OTR' (name of an encryption protocol) # Variables: # $error (String) - contains an error message that describes the cause of the failure diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/preferences/am-im.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/preferences/am-im.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/preferences/am-im.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/preferences/am-im.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -4,6 +4,8 @@ account-settings-title = Authentication Settings account-channel-title = Default Channels +chat-autologin = + .label = Sign-on at startup chat-encryption-generic = Generic chat-encryption-log = .label = Include end-to-end encrypted messages in conversation logs diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/preferences/dock-options.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/preferences/dock-options.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/preferences/dock-options.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/preferences/dock-options.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -21,3 +21,4 @@ .label = Count of new messages .accesskey = n notification-settings-info = You can disable the badge on the Notification pane of System Preferences. +notification-settings-info2 = You can disable the badge on the Notification pane of System Settings. diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/mail/messenger/preferences/preferences.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -4,111 +4,72 @@ close-button = .aria-label = Close - preferences-doc-title = Preferences - +preferences-doc-title2 = Settings category-list = .aria-label = Categories - pane-general-title = General category-general = .tooltiptext = { pane-general-title } - pane-compose-title = Composition category-compose = .tooltiptext = Composition - pane-privacy-title = Privacy & Security category-privacy = .tooltiptext = Privacy & Security - pane-chat-title = Chat category-chat = .tooltiptext = Chat - pane-calendar-title = Calendar category-calendar = .tooltiptext = Calendar - general-language-and-appearance-header = Language & Appearance - general-incoming-mail-header = Incoming Mails - general-files-and-attachment-header = Files & Attachments - general-tags-header = Tags - general-reading-and-display-header = Reading & Display - general-updates-header = Updates - general-network-and-diskspace-header = Network & Disk Space - general-indexing-label = Indexing - composition-category-header = Composition - composition-attachments-header = Attachments - composition-spelling-title = Spelling - compose-html-style-title = HTML Style - composition-addressing-header = Addressing - privacy-main-header = Privacy - privacy-passwords-header = Passwords - privacy-junk-header = Junk - collection-header = { -brand-short-name } Data Collection and Use - collection-description = We strive to provide you with choices and collect only what we need to provide and improve { -brand-short-name } for everyone. We always ask permission before receiving personal information. collection-privacy-notice = Privacy Notice - collection-health-report-telemetry-disabled = You’re no longer allowing { -vendor-short-name } to capture technical and interaction data. All past data will be deleted within 30 days. collection-health-report-telemetry-disabled-link = Learn more - collection-health-report = .label = Allow { -brand-short-name } to send technical and interaction data to { -vendor-short-name } .accesskey = r collection-health-report-link = Learn more - # This message is displayed above disabled data sharing options in developer builds # or builds with no Telemetry support available. collection-health-report-disabled = Data reporting is disabled for this build configuration - collection-backlogged-crash-reports = .label = Allow { -brand-short-name } to send backlogged crash reports on your behalf .accesskey = c collection-backlogged-crash-reports-link = Learn more - privacy-security-header = Security - privacy-scam-detection-title = Scam Detection - privacy-anti-virus-title = Antivirus - privacy-certificates-title = Certificates - chat-pane-header = Chat - chat-status-title = Status - chat-notifications-title = Notifications - chat-pane-styling-header = Styling - choose-messenger-language-description = Choose the languages used to display menus, messages, and notifications from { -brand-short-name }. manage-messenger-languages-button = .label = Set Alternatives… .accesskey = l confirm-messenger-language-change-description = Restart { -brand-short-name } to apply these changes confirm-messenger-language-change-button = Apply and Restart - update-setting-write-failure-title = Error saving Update preferences - # Variables: # $path (String) - Path to the configuration file # The newlines between the main text and the line containing the path is @@ -117,16 +78,12 @@ { -brand-short-name } encountered an error and didn’t save this change. Note that setting this update preference requires permission to write to the file below. You or a system administrator may be able resolve the error by granting the Users group full control to this file. Could not write to file: { $path } - update-in-progress-title = Update In Progress - update-in-progress-message = Do you want { -brand-short-name } to continue with this update? - update-in-progress-ok-button = &Discard # Continue is the cancel button so pressing escape or using a platform standard # method of closing the UI will not discard the update. update-in-progress-cancel-button = &Continue - account-button = Account Settings open-addons-sidebar-button = Add-ons and Themes @@ -134,13 +91,11 @@ # This message can be seen by trying to add a Primary Password. primary-password-os-auth-dialog-message-win = To create a Primary Password, enter your Windows login credentials. This helps protect the security of your accounts. - # This message can be seen by trying to add a Primary Password. # The macOS strings are preceded by the operating system with "Thunderbird is trying to " # and includes subtitle of "Enter password for the user "xxx" to allow this." These # notes are only valid for English. Please test in your locale. primary-password-os-auth-dialog-message-macosx = create a Primary Password - # Don't change this label. master-password-os-auth-dialog-caption = { -brand-full-name } @@ -150,32 +105,30 @@ .key = f focus-search-shortcut-alt = .key = k - general-legend = { -brand-short-name } Start Page - start-page-label = .label = When { -brand-short-name } launches, show the Start Page in the message area .accesskey = W - location-label = .value = Location: .accesskey = o restore-default-label = .label = Restore Default .accesskey = R - default-search-engine = Default Search Engine -add-search-engine = - .label = Add from file +add-web-search-engine = + .label = Add… .accesskey = A remove-search-engine = .label = Remove .accesskey = v - +add-opensearch-provider-title = Add OpenSearch Provider +add-opensearch-provider-text = Enter the URL of the OpenSearch provider to add. Either use the direct URL of the OpenSearch Description file, or a URL where it can be auto-discovered. +adding-opensearch-provider-failed-title = Adding OpenSearch Provider Failed +adding-opensearch-provider-failed-text = Could not add OpenSearch Provider for { $url }. minimize-to-tray-label = .label = When { -brand-short-name } is minimized, move it to the tray .accesskey = m - new-message-arrival = When new messages arrive: mail-play-sound-label = .label = @@ -191,30 +144,24 @@ mail-play-button = .label = Play .accesskey = P - change-dock-icon = Change preferences for the app icon app-icon-options = .label = App Icon Options… .accesskey = n - notification-settings = Alerts and the default sound can be disabled on the Notification pane of System Preferences. - +notification-settings2 = Alerts and the default sound can be disabled on the Notification pane of System Settings. animated-alert-label = .label = Show an alert .accesskey = S customize-alert-label = .label = Customize… .accesskey = C - biff-use-system-alert = .label = Use the system notification - tray-icon-unread-label = .label = Show a tray icon for unread messages .accesskey = t - tray-icon-unread-description = Recommended when using small taskbar buttons - mail-system-sound-label = .label = Default system sound for new mail .accesskey = D @@ -224,27 +171,21 @@ mail-browse-sound-button = .label = Browse… .accesskey = B - enable-gloda-search-label = .label = Enable Global Search and Indexer .accesskey = G - datetime-formatting-legend = Date and Time Formatting language-selector-legend = Language - allow-hw-accel = .label = Use hardware acceleration when available .accesskey = h - store-type-label = .value = Message Store Type for new accounts: .accesskey = T - mbox-store-label = .label = File per folder (mbox) maildir-store-label = .label = File per message (maildir) - scrolling-legend = Scrolling autoscroll-label = .label = Use autoscrolling @@ -252,7 +193,9 @@ smooth-scrolling-label = .label = Use smooth scrolling .accesskey = m - +browsing-gtk-use-non-overlay-scrollbars = + .label = Always show scrollbars + .accesskey = c system-integration-legend = System Integration always-check-default = .label = Always check to see if { -brand-short-name } is the default mail client on startup @@ -260,7 +203,6 @@ check-default-button = .label = Check Now… .accesskey = N - # Note: This is the search engine name for all the different platforms. # Platforms that don't support it should be left blank. search-engine-name = @@ -269,26 +211,20 @@ [windows] Windows Search *[other] { "" } } - search-integration-label = .label = Allow { search-engine-name } to search messages .accesskey = S - config-editor-button = .label = Config Editor… .accesskey = C - return-receipts-description = Determine how { -brand-short-name } handles return receipts return-receipts-button = .label = Return Receipts… .accesskey = R - update-app-legend = { -brand-short-name } Updates - # Variables: # $version (String): version of Thunderbird, e.g. 68.0.1 update-app-version = Version { $version } - allow-description = Allow { -brand-short-name } to automatic-updates-label = .label = Automatically install updates (recommended: improved security) @@ -296,40 +232,30 @@ check-updates-label = .label = Check for updates, but let me choose whether to install them .accesskey = C - update-history-button = .label = Show Update History .accesskey = p - use-service = .label = Use a background service to install updates .accesskey = b - cross-user-udpate-warning = This setting will apply to all Windows accounts and { -brand-short-name } profiles using this installation of { -brand-short-name }. - networking-legend = Connection proxy-config-description = Configure how { -brand-short-name } connects to the Internet - network-settings-button = .label = Settings… .accesskey = S - offline-legend = Offline offline-settings = Configure offline settings - offline-settings-button = .label = Offline… .accesskey = O - diskspace-legend = Disk Space offline-compact-folder = .label = Compact all folders when it will save over .accesskey = a - offline-compact-folder-automatically = .label = Ask every time before compacting .accesskey = b - compact-folder-size = .value = MB in total @@ -340,7 +266,6 @@ use-cache-before = .value = Use up to .accesskey = U - use-cache-after = MB of space for the cache ## @@ -348,42 +273,31 @@ smart-cache-label = .label = Override automatic cache management .accesskey = v - clear-cache-button = .label = Clear Now .accesskey = C - fonts-legend = Fonts & Colours - default-font-label = .value = Default font: .accesskey = D - default-size-label = .value = Size: .accesskey = S - font-options-button = .label = Advanced… .accesskey = A - color-options-button = .label = Colours… .accesskey = C - display-width-legend = Plain Text Messages - # Note : convert-emoticons-label 'Emoticons' are also known as 'Smileys', e.g. :-) convert-emoticons-label = .label = Display emoticons as graphics .accesskey = e - display-text-label = When displaying quoted plain text messages: - style-label = .value = Style: .accesskey = y - regular-style-item = .label = Regular bold-style-item = @@ -392,37 +306,25 @@ .label = Italic bold-italic-style-item = .label = Bold Italic - size-label = .value = Size: .accesskey = z - regular-size-item = .label = Regular bigger-size-item = .label = Bigger smaller-size-item = .label = Smaller - quoted-text-color = .label = Colour: .accesskey = o - search-handler-table = .placeholder = Filter content types and actions - -type-column-label = - .label = Content Type - .accesskey = T - -action-column-label = - .label = Action - .accesskey = A - +type-column-header = Content Type +action-column-header = Action save-to-label = .label = Save files to .accesskey = S - choose-folder-label = .label = { PLATFORM() -> @@ -434,30 +336,22 @@ [macos] C *[other] B } - always-ask-label = .label = Always ask me where to save files .accesskey = A - - display-tags-text = Tags can be used to categorize and prioritize your messages. - new-tag-button = .label = New… .accesskey = N - edit-tag-button = .label = Edit… .accesskey = E - delete-tag-button = .label = Delete .accesskey = D - auto-mark-as-read = .label = Automatically mark messages as read .accesskey = A - mark-read-no-delay = .label = Immediately on display .accesskey = o @@ -468,33 +362,26 @@ mark-read-delay = .label = After displaying for .accesskey = d - seconds-label = seconds ## open-msg-label = .value = Open messages in: - open-msg-tab = .label = A new tab .accesskey = t - open-msg-window = .label = A new message window .accesskey = n - open-msg-ex-window = .label = An existing message window .accesskey = e - close-move-delete = .label = Close message window/tab on move or delete .accesskey = C - display-name-label = .value = Display name: - condensed-addresses-label = .label = Show only display name for people in my address book .accesskey = S @@ -504,13 +391,10 @@ forward-label = .value = Forward messages: .accesskey = F - inline-label = .label = Inline - as-attachment-label = .label = As Attachment - extension-label = .label = add extension to file name .accesskey = e @@ -521,7 +405,6 @@ auto-save-label = .label = Auto Save every .accesskey = A - auto-save-end = minutes ## @@ -529,248 +412,182 @@ warn-on-send-accel-key = .label = Confirm when using keyboard shortcut to send message .accesskey = C - spellcheck-label = .label = Check spelling before sending .accesskey = C - spellcheck-inline-label = .label = Enable spellcheck as you type .accesskey = E - language-popup-label = .value = Language: .accesskey = L - download-dictionaries-link = Download More Dictionaries - font-label = .value = Font: .accesskey = n - font-size-label = .value = Size: .accesskey = z - default-colors-label = .label = Use reader’s default colours .accesskey = d - font-color-label = .value = Text Colour: .accesskey = T - bg-color-label = .value = Background Colour: .accesskey = B - restore-html-label = .label = Restore Defaults .accesskey = R - default-format-label = .label = Use Paragraph format instead of Body Text by default .accesskey = P - format-description = Configure text format behaviour - send-options-label = .label = Send Options… .accesskey = S - autocomplete-description = When addressing messages, look for matching entries in: - ab-label = .label = Local Address Books .accesskey = L - directories-label = .label = Directory Server: .accesskey = D - directories-none-label = .none = None - edit-directories-label = .label = Edit Directories… .accesskey = E - email-picker-label = .label = Automatically add outgoing e-mail addresses to my: .accesskey = A - default-directory-label = .value = Default startup directory in the address book window: .accesskey = S - default-last-label = .none = Last used directory - attachment-label = .label = Check for missing attachments .accesskey = m - attachment-options-label = .label = Keywords… .accesskey = K - enable-cloud-share = .label = Offer to share for files larger than cloud-share-size = .value = MB - add-cloud-account = .label = Add… .accesskey = A .defaultlabel = Add… - remove-cloud-account = .label = Remove .accesskey = R - find-cloud-providers = .value = Find more providers… - cloud-account-description = Add a new Filelink storage service ## Privacy Tab mail-content = Mail Content - remote-content-label = .label = Allow remote content in messages .accesskey = m - exceptions-button = .label = Exceptions… .accesskey = E - remote-content-info = .value = Learn more about the privacy issues of remote content - web-content = Web Content - history-label = .label = Remember websites and links I’ve visited .accesskey = R - cookies-label = .label = Accept cookies from sites .accesskey = A - third-party-label = .value = Accept third-party cookies: .accesskey = c - third-party-always = .label = Always third-party-never = .label = Never third-party-visited = .label = From visited - keep-label = .value = Keep until: .accesskey = K - keep-expire = .label = they expire keep-close = .label = I close { -brand-short-name } keep-ask = .label = ask me every time - cookies-button = .label = Show Cookies… .accesskey = S - do-not-track-label = .label = Send websites a “Do Not Track” signal that you don’t want to be tracked .accesskey = n - learn-button = .label = Learn more - passwords-description = { -brand-short-name } can remember passwords for all of your accounts. - passwords-button = .label = Saved Passwords… .accesskey = S - primary-password-description = A Primary Password protects all your passwords, but you must enter it once per session. - primary-password-label = .label = Use a Primary Password .accesskey = U - primary-password-button = .label = Change Primary Password… .accesskey = C - forms-primary-pw-fips-title = You are currently in FIPS mode. FIPS requires a non-empty Primary Password. forms-master-pw-fips-desc = Password Change Failed - - junk-description = Set your default junk mail settings. Account-specific junk mail settings can be configured in Account Settings. - junk-label = .label = When I mark messages as junk: .accesskey = W - junk-move-label = .label = Move them to the account’s "Junk" folder .accesskey = o - junk-delete-label = .label = Delete them .accesskey = D - junk-read-label = .label = Mark messages determined to be Junk as read .accesskey = M - junk-log-label = .label = Enable adaptive junk filter logging .accesskey = E - junk-log-button = .label = Show log .accesskey = S - reset-junk-button = .label = Reset Training Data .accesskey = R - phishing-description = { -brand-short-name } can analyze messages for suspected email scams by looking for common techniques used to deceive you. - phishing-label = .label = Tell me if the message I’m reading is a suspected email scam .accesskey = T - antivirus-description = { -brand-short-name } can make it easy for antivirus software to analyze incoming mail messages for viruses before they are stored locally. - antivirus-label = .label = Allow antivirus clients to quarantine individual incoming messages .accesskey = A - certificate-description = When a server requests my personal certificate: - certificate-auto = .label = Select one automatically .accesskey = S - certificate-ask = .label = Ask me every time .accesskey = A - ocsp-label = .label = Query OCSP responder servers to confirm the current validity of certificates .accesskey = Q - certificate-button = .label = Manage Certificates… .accesskey = M - security-devices-button = .label = Security Devices… .accesskey = D @@ -780,10 +597,8 @@ startup-label = .value = When { -brand-short-name } starts: .accesskey = s - offline-label = .label = Keep my Chat Accounts offline - auto-connect-label = .label = Connect my chat accounts automatically @@ -796,7 +611,6 @@ idle-label = .label = Let my contacts know that I am Idle after .accesskey = I - idle-time-label = minutes of inactivity ## @@ -804,24 +618,19 @@ away-message-label = .label = and set my status to Away with this status message: .accesskey = A - send-typing-label = .label = Send typing notifications in conversations .accesskey = t - notification-label = When messages directed at you arrive: - show-notification-label = .label = Show a notification: .accesskey = c - notification-all = .label = with sender’s name and message preview notification-name = .label = with sender’s name only notification-empty = .label = without any info - notification-type-label = .label = { PLATFORM() -> @@ -833,31 +642,24 @@ [macos] o *[other] F } - chat-play-sound-label = .label = Play a sound .accesskey = d - chat-play-button = .label = Play .accesskey = P - chat-system-sound-label = .label = Default system sound for new mail .accesskey = D - chat-custom-sound-label = .label = Use the following sound file .accesskey = U - chat-browse-sound-button = .label = Browse… .accesskey = B - theme-label = .value = Theme: .accesskey = T - style-thunderbird = .label = Thunderbird style-bubbles = @@ -868,15 +670,12 @@ .label = Paper Sheets style-simple = .label = Simple - preview-label = Preview: no-preview-label = No preview available no-preview-description = This theme is not valid or is currently unavailable (disabled add-on, safe-mode, …). - chat-variant-label = .value = Variant: .accesskey = V - # This is used to determine the width of the search field in about:preferences, # in order to make the entire placeholder string visible # @@ -891,13 +690,31 @@ ## Preferences UI Search Results -search-results-header = Search Results +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input2 = + .style = width: 15.4em + .placeholder = Find in Settings +## Settings UI Search Results + +search-results-header = Search Results # `` will be replaced by the search term. search-results-empty-message = { PLATFORM() -> [windows] Sorry! There are no results in Options for “”. *[other] Sorry! There are no results in Preferences for “”. } - +# `` will be replaced by the search term. +search-results-empty-message2 = + { PLATFORM() -> + [windows] Sorry! There are no results in Options for “”. + *[other] Sorry! There are no results in Settings for “”. + } search-results-help-link = Need help? Visit { -brand-short-name } Support diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/en-CA/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/en-CA/netwerk/necko.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/netwerk/necko.properties 2022-04-15 07:51:59.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Cookie “%1$S” has been rejected because it is already expired. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Cookie “%1$S” has been rejected because it is in a cross-site context and its “SameSite” is “Lax” or “Strict”. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Warning: ‘%1$S’ deprecated, please use ‘%2$S’ diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/en-CA/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:51:59.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Close Reader View @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Colour Scheme Light aboutReader.toolbar.colorschemedark = Colour Scheme Dark aboutReader.toolbar.colorschemesepia = Colour Scheme Sepia +aboutReader.toolbar.colorschemeauto = Color Scheme Auto diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/en-CA/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/chrome/global/narrate.properties 2022-04-15 07:51:59.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Listen back = Back start = Start stop = Stop +# %S is the keyboard shortcut for the start command +start-label = Start (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Stop (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Forward speed = Speed selectvoicelabel = Voice: diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/chrome/mozapps/extensions/extensions.properties thunderbird-91.8.1+build1/l10n/en-CA/toolkit/chrome/mozapps/extensions/extensions.properties --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/chrome/mozapps/extensions/extensions.properties 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/chrome/mozapps/extensions/extensions.properties 2022-04-15 07:51:59.000000000 +0000 @@ -68,6 +68,7 @@ type.plugin.name=Plugins type.dictionary.name=Dictionaries type.service.name=Services +type.sitepermission.name=Site Permissions type.legacy.name=Legacy Extensions type.unsupported.name=Unsupported @@ -80,5 +81,7 @@ listHeading.locale=Manage Your Languages listHeading.dictionary=Manage Your Dictionaries +listHeading.sitepermission=Manage Your Site Permissions + searchLabel.extension=Find more extensions searchLabel.theme=Find more themes diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/about/aboutAddons.ftl thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/about/aboutAddons.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/about/aboutAddons.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/about/aboutAddons.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -137,6 +137,9 @@ addon-category-recent-updates = Recent Updates addon-category-recent-updates-title = .title = Recent Updates +addon-category-sitepermission = Site Permissions +addon-category-sitepermission-title = + .title = Site Permissions ## These are global warnings @@ -292,6 +295,8 @@ dictionary-disabled-heading = Disabled locale-enabled-heading = Enabled locale-disabled-heading = Disabled +sitepermission-enabled-heading = Enabled +sitepermission-disabled-heading = Disabled always-activate-button = Always Activate never-activate-button = Never Activate addon-detail-author-label = Author @@ -368,6 +373,7 @@ addon-permissions-learnmore = Learn more about permissions recommended-extensions-heading = Recommended Extensions recommended-themes-heading = Recommended Themes +addon-sitepermissions-required = Grants the following capabilities to { $hostname }: # A recommendation for the Firefox Color theme shown at the bottom of the theme # list view. The "Firefox Color" name itself should not be translated. recommended-theme-1 = Feeling creative? Build your own theme with Firefox Color. @@ -380,6 +386,7 @@ dictionary-heading = Manage Your Dictionaries locale-heading = Manage Your Languages updates-heading = Manage Your Updates +sitepermission-heading = Manage Your Site Permissions discover-heading = Personalize Your { -brand-short-name } shortcuts-heading = Manage Extension Shortcuts default-heading-search-label = Find more add-ons diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -18,6 +18,8 @@ about-webrtc-aec-logging-off-state-label = Start AEC Logging about-webrtc-aec-logging-on-state-label = Stop AEC Logging about-webrtc-aec-logging-on-state-msg = AEC logging active (speak with the caller for a few minutes and then stop the capture) +# The autorefresh checkbox causes the page to autorefresh its content when checked +about-webrtc-auto-refresh-label = Auto Refresh ## @@ -183,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } frame + *[other] { $frames } frames + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } channel + *[other] { $channels } channels + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/about/abuseReports.ftl thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/about/abuseReports.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/about/abuseReports.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/about/abuseReports.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -8,19 +8,16 @@ # Variables: # $addon-name (string) - Name of the add-on being reported abuse-report-dialog-title = Report for { $addon-name } - abuse-report-title-extension = Report This Extension to { -vendor-short-name } +abuse-report-title-sitepermission = Report This Site Permissions add-on to { -vendor-short-name } abuse-report-title-theme = Report This Theme to { -vendor-short-name } abuse-report-subtitle = What’s the issue? - # Variables: # $author-name (string) - Name of the add-on author abuse-report-addon-authored-by = by { $author-name } - abuse-report-learnmore = Unsure what issue to select? Learn more about reporting extensions and themes - abuse-report-submit-description = Describe the problem (optional) abuse-report-textarea = .placeholder = It’s easier for us to address a problem if we have specifics. Please describe what you’re experiencing. Thank you for helping us keep the web healthy. @@ -36,12 +33,6 @@ abuse-report-submit-button = Submit ## Message bars descriptions. - - -## Variables: -## $addon-name (string) - Name of the add-on - -## Message bars descriptions. ## ## Variables: ## $addon-name (string) - Name of the add-on @@ -51,6 +42,7 @@ abuse-report-messagebar-submitted = Thank you for submitting a report. Do you want to remove { $addon-name }? abuse-report-messagebar-submitted-noremove = Thank you for submitting a report. abuse-report-messagebar-removed-extension = Thank you for submitting a report. You’ve removed the extension { $addon-name }. +abuse-report-messagebar-removed-sitepermission = Thank you for submitting a report. You’ve removed the Site Permissions add-on { $addon-name }. abuse-report-messagebar-removed-theme = Thank you for submitting a report. You’ve removed the theme { $addon-name }. abuse-report-messagebar-error = There was an error sending the report for { $addon-name }. abuse-report-messagebar-error-recent-submit = The report for { $addon-name } wasn’t sent because another report was submitted recently. @@ -59,6 +51,8 @@ abuse-report-messagebar-action-remove-extension = Yes, Remove It abuse-report-messagebar-action-keep-extension = No, I’ll Keep It +abuse-report-messagebar-action-remove-sitepermission = Yes, Remove It +abuse-report-messagebar-action-keep-sitepermission = No, I’ll Keep It abuse-report-messagebar-action-remove-theme = Yes, Remove It abuse-report-messagebar-action-keep-theme = No, I’ll Keep It abuse-report-messagebar-action-retry = Retry @@ -68,38 +62,35 @@ abuse-report-damage-reason-v2 = It damaged my computer or compromised my data abuse-report-damage-example = Example: Injected malware or stole data - abuse-report-spam-reason-v2 = It contains spam or inserts unwanted advertising abuse-report-spam-example = Example: Insert ads on webpages - abuse-report-settings-reason-v2 = It changed my search engine, homepage, or new tab without informing or asking me abuse-report-settings-suggestions = Before reporting the extension, you can try changing your settings: abuse-report-settings-suggestions-search = Change your default search settings abuse-report-settings-suggestions-homepage = Change your homepage and new tab - abuse-report-deceptive-reason-v2 = It claims to be something it’s not abuse-report-deceptive-example = Example: Misleading description or imagery - abuse-report-broken-reason-extension-v2 = It doesn’t work, breaks websites, or slows down { -brand-product-name } +abuse-report-broken-reason-sitepermission-v2 = It doesn’t work, breaks websites, or slows down { -brand-product-name } abuse-report-broken-reason-theme-v2 = It doesn’t work or breaks browser display abuse-report-broken-example = Example: Features are slow, hard to use, or don’t work; parts of websites won’t load or look unusual abuse-report-broken-suggestions-extension = It sounds like you’ve identified a bug. In addition to submitting a report here, the best way to get a functionality issue resolved is to contact the extension developer. Visit the extension’s website to get the developer information. +abuse-report-broken-suggestions-sitepermission = + It sounds like you’ve identified a bug. In addition to submitting a report here, the best way + to get a functionality issue resolved is to contact the website developer. + Visit the website to get the developer information. abuse-report-broken-suggestions-theme = It sounds like you’ve identified a bug. In addition to submitting a report here, the best way to get a functionality issue resolved is to contact the theme developer. Visit the theme’s website to get the developer information. - abuse-report-policy-reason-v2 = It contains hateful, violent, or illegal content abuse-report-policy-suggestions = Note: Copyright and trademark issues must be reported in a separate process. Use these instructions to report the problem. - abuse-report-unwanted-reason-v2 = I never wanted it and don’t know how to get rid of it abuse-report-unwanted-example = Example: An application installed it without my permission - abuse-report-other-reason = Something else - diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -9,11 +9,6 @@ experimental-features-css-masonry-description = Enables support for the experimental CSS Masonry Layout feature. See the explainer for a high level description of the feature. To provide feedback, please comment in this GitHub issue or this bug. # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. -experimental-features-css-cascade-layers = - .label = CSS: Cascade Layers -experimental-features-css-cascade-layers-description = Enables support for CSS Cascade Layers. See the in-progress specification for details. File bugs blocking bug 1699215 for bugs related to this feature. -# The title of the experiment should be kept in English as it may be referenced -# by various online articles and is technical in nature. experimental-features-web-gpu2 = .label = Web API: WebGPU experimental-features-web-gpu-description2 = This new API provides low-level support for performing computation and graphics rendering using the Graphics Processing Unit (GPU) of the user’s device or computer. The specification is still a work-in-progress. See bug 1602129 for more details. @@ -94,3 +89,7 @@ experimental-features-ime-search = .label = Address Bar: show results during IME composition experimental-features-ime-search-description = An IME (Input Method Editor) is a tool that allows you to enter complex symbols, such as those used in East Asian or Indic written languages, using a standard keyboard. Enabling this experiment will keep the address bar panel open, showing search results and suggestions, while using IME to input text. Note that the IME might display a panel that covers the address bar results, therefore this preference is only suggested for IME not using this type of panel. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name } 100 User-Agent String +experimental-features-firefox-100-description = Make { -brand-short-name } send websites a User-Agent string that pretends to be { -brand-product-name } version 100. Use this setting to test whether websites will break when { -brand-short-name } hits a three-digit version number. The real { -brand-product-name } 100 is scheduled to be released in May 2022, so start testing your websites now! diff -Nru thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/en-CA/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:37:14.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-CA/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:51:59.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socket # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Sandboxed IPC Actor ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/en-GB/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Privacy: Private Event calendar-editable-item-privacy-icon-confidential = .alt = Privacy: Show Time and Date Only +calendar-editable-item-recurrence = + .alt = Recurring +calendar-editable-item-recurrence-exception = + .alt = Recurrence exception calendar-editable-item-todo-icon-task = .alt = Task calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/en-GB/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:52:07.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } has invited you to: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Save +calendar-invitation-panel-accept-button = Yes +calendar-invitation-panel-decline-button = No +calendar-invitation-panel-tentative-button = Maybe +calendar-invitation-panel-reply-status = * You have not decided or responded yet +calendar-invitation-panel-prop-title-when = When: +calendar-invitation-panel-prop-title-location = Location: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Attendees: +calendar-invitation-panel-prop-title-description = Description: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } yes + [DECLINED] { $count } no + [TENTATIVE] { $count } maybe + [NEEDS-ACTION] { $count } pending + [TOTAL] { $count } participants + *[OTHER] { $count } other + } diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/chat/matrix.properties thunderbird-91.8.1+build1/l10n/en-GB/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/en-GB/chat/matrix.properties 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/chat/matrix.properties 2022-04-15 07:52:06.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S cancelled the verification with the reason: %2$S message.verification.done=Verification completed. +message.decryptionError=Could not decrypt the contents of this message. To request encryption keys from your other devices, right click this message. +message.decrypting=Decrypting... +message.redacted=Message was redacted. + +# Label in the message context menu +message.action.requestKey=Re-request Keys +message.action.redact=Redact +message.action.report=Report Message +message.action.retry=Retry Sending +message.action.cancel=Cancel Message + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=An error occurred while sending your message "%1$S". diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/aboutdebugging.ftl 2022-03-07 21:37:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/aboutdebugging.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Debugging - Setup - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Debugging - Runtime / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = This { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Setup - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB enabled - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB disabled - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Connected # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Disconnected - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = No devices discovered - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Connect - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Connecting… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Connection failed - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = Connection still pending, check for messages on the target browser - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = Connection timed out - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Waiting for browser… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Unplugged - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Debugging Support - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Help icon - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Refresh devices @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Setup - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Configure the connection method you wish to remotely debug your device with. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Use { about-debugging-this-firefox-runtime-name } to debug extensions and service workers on this version of { -brand-shorter-name }. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Connect a Device - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Enabling this will download and add the required Android USB debugging components to { -brand-shorter-name }. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = Enable USB Devices - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = Disable USB Devices - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Updating… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Enabled about-debugging-setup-usb-status-disabled = Disabled about-debugging-setup-usb-status-updating = Updating… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Enable Developer menu on your Android device. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Enable USB Debugging in the Android Developer Menu. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Enable USB Debugging in Firefox on the Android device. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Connect the Android device to your computer. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Problems connecting to the USB device? Troubleshoot - # Network section of the Setup page about-debugging-setup-network = .title = Network Location - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Problems connecting via network location? Troubleshoot - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Add - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = No network locations have been added yet. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Host - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Remove - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Invalid host “{ $host-value }”. The expected format is “hostname:portnumber”. - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Processes - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Profile performance - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Your browser configuration is not compatible with Service Workers. Learn more - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = The connected browser has an old version ({ $runtimeVersion }). The minimum supported version is ({ $minVersion }). This is an unsupported setup and may cause DevTools to fail. Please update the connected browser. Troubleshooting - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = This version of Firefox cannot debug Firefox for Android (68). We recommend installing Firefox for Android Nightly on your phone for testing. More details - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = The connected browser is more recent ({ $runtimeVersion }, buildID { $runtimeID }) than your { -brand-shorter-name } ({ $localVersion }, buildID { $localID }). This is an unsupported setup and may cause DevTools to fail. Please update Firefox. Troubleshooting - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Disconnect - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Enable connection prompt - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Disable connection prompt - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Profiler - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Nothing yet. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Inspect - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Load Temporary Add-on… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = There was an error during the temporary add-on installation. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Reload - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Remove - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Terminate background script # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Select manifest.json file or .xpi/.zip archive - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = This WebExtension has a temporary ID. Learn more - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = Manifest URL - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = Internal UUID - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Location - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = Extension ID - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Background script +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Running +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Stopped # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push .disabledTitle = Service Worker push is currently disabled for multiprocess { -brand-shorter-name } - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Start .disabledTitle = Service Worker start is currently disabled for multiprocess { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Unregister - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Listening for fetch events - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = Not listening for fetch events - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Running - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Stopped - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Registering - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Scope - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Push Service - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = Service Worker inspection is currently disabled for multiprocess { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Tab is not fully loaded and cannot be inspected - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Main Process - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Main Process for the target browser - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Multiprocess Toolbox - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Main Process and Content Processes for the target browser - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Close message - # Label text used for the error details of message component. about-debugging-message-details-label-error = Error details - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Warning details - # Label text used for default state of details of message component. about-debugging-message-details-label = Details diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/compatibility.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/compatibility.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (experimental) compatibility-issue-prefixneeded = (prefix needed) compatibility-issue-deprecated-experimental = (deprecated, experimental) - compatibility-issue-deprecated-prefixneeded = (deprecated, prefix needed) compatibility-issue-experimental-prefixneeded = (experimental, prefix needed) compatibility-issue-deprecated-experimental-prefixneeded = (deprecated, experimental, prefix needed) @@ -43,7 +42,14 @@ [one] { $number } occurrence *[other] { $number } occurrences } - compatibility-no-issues-found = No compatibility issues found. compatibility-close-settings-button = .title = Close settings +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Compatibility issues in: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/netmonitor.properties 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/netmonitor.properties 2022-04-15 07:52:06.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=The string “%S” was removed from the beginning of the JSON shown below + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Query String +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL Parameters + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Request Headers +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Headers + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=name + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=value + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Body + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=payload + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Request Body @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Cancel +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Clear + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Remove item + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Back diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/toolbox-options.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/toolbox-options.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Enable remote debugging options-enable-remote-tooltip2 = .title = Turning this option on will allow to debug this browser instance remotely +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Enable custom formatters +options-enable-custom-formatters-tooltip = + .title = Turning this option on will allow sites to define custom formatters for DOM objects # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Enable Service Workers over HTTP (when toolbox is open) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/en-GB/devtools/client/webconsole.properties 2022-03-07 21:37:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/devtools/client/webconsole.properties 2022-04-15 07:52:06.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=File +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Copy all Messages +webconsole.menu.copyAllMessages.accesskey=M + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Save all Messages to File +webconsole.menu.saveAllMessagesFile.accesskey=F + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/en-GB/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/en-GB/dom/chrome/dom/dom.properties 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/dom/chrome/dom/dom.properties 2022-04-15 07:52:07.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Please enter a URL. FormValidationInvalidDate=Please enter a valid date. FormValidationInvalidTime=Please enter a valid time. +FormValidationInvalidDateTime=Please enter valid date and time. +FormValidationInvalidDateMonth=Please enter a valid month. +FormValidationInvalidDateWeek=Please enter a valid week. FormValidationPatternMismatch=Please match the requested format. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Please match the requested format: %S. diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/en-GB/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/en-GB/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:37:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:52:06.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/aboutDialog.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = What’s New diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/aboutImport.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/aboutImport.ftl 2022-04-15 07:52:07.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Choose to import Accounts, Address Books, Calendars, and other data from: import-address-book = Import Address Book File import-calendar = Import Calendar File +export-profile = Export ## Buttons button-cancel = Cancel button-back = Back button-continue = Continue +button-export = Export ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Import from { $app } @@ -26,17 +33,52 @@ profile-file-picker-dir = Select a profile folder profile-file-picker-zip = Select a zip file (smaller than 2GB) items-pane-title = Select what to import -items-pane-desc = Import from +items-pane-source = Source location: items-pane-checkbox-accounts = Accounts and Settings items-pane-checkbox-address-books = Address Books items-pane-checkbox-calendars = Calendars items-pane-checkbox-mail-messages = Mail Messages +## Import from address book file steps + +import-from-addr-book-file-desc = Select the file type you would like to import: +addr-book-csv-file = Comma or tab separated file (.csv, .tsv) +addr-book-ldif-file = LDIF file (.ldif) +addr-book-vcard-file = vCard file (.vcf, .vcard) +addr-book-sqlite-file = SQLite database file (.sqlite) +addr-book-mab-file = Mork database file (.mab) +addr-book-file-picker = Select an address book file +addr-book-csv-field-map-title = Match field names +addr-book-csv-field-map-desc = Select address book fields corresponding to the source fields. Untick fields you do not want to import. +addr-book-directories-pane-title = Select the directory you would like to import into: +addr-book-directories-pane-source = Source file: +addr-book-import-into-new-directory = Create a new directory + ## Import dialog progress-pane-title = Importing +progress-pane-importing = Importing +progress-pane-exporting = Exporting +progress-pane-finished-desc = Finished. progress-pane-restart-desc = Restart to finish importing. error-pane-title = Error error-message-zip-file-too-big = The selected zip file is larger than 2GB. Please extract it first, then import from the extracted folder instead. error-message-extract-zip-file-failed = Failed to extract the zip file. Please extract it manually, then import from the extracted folder instead. error-message-failed = Import failed unexpectedly, more information may be available in the Error Console. +error-export-failed = Export failed unexpectedly, more information may be available in the Error Console. + +## element + +csv-first-row-contains-headers = First row contains field names +csv-source-field = Source field +csv-source-first-record = First record +csv-source-second-record = Second record +csv-target-field = Address book field + +## Export tab + +export-profile-desc = Export mail accounts, mail messages, address books, and settings to a zip file. When needed, you can import the zip file to restore your profile. +export-profile-desc2 = If your current profile is larger than 2GB, we suggest you back it up by yourself. +export-open-profile-folder = Open profile folder +export-file-picker = Export to a zip file +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = New CardDAV Address Book - +carddav-window-title = New CardDAV Address Book carddav-dialog = .buttonlabelaccept = Continue .buttonaccesskeyaccept = C - carddav-username-label = .value = Username: .accesskey = U - carddav-location-label = .value = Location: .accesskey = L carddav-location = .default-placeholder = URL or host name of the address book server - carddav-loading = Looking up configuration… carddav-known-incompatible = { $url } is known to be incompatible with { -brand-short-name }. carddav-connection-error = Failed to connect. carddav-none-found = Found no address books to add for the specified account. carddav-already-added = All address books for the specified account have already been added. - carddav-available-books = Available address books: diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -132,8 +132,8 @@ about-addressbook-details-home-address-header = Home Address about-addressbook-details-work-address-header = Work Address about-addressbook-details-other-info-header = Other Information -about-addressbook-prompt-to-save-title = Save Changes? -about-addressbook-prompt-to-save = Do you want to save your changes? +about-addressbook-unsaved-changes-prompt-title = Unsaved Changes +about-addressbook-unsaved-changes-prompt = Do you want to save your changes before leaving the edit view? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:52:07.000000000 +0000 @@ -86,6 +86,12 @@ .tooltiptext = Show the attachment pane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Hide the attachment pane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } Attachment + *[other] { $count } Attachments + } attachment-area-show = .title = Show the attachment pane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -241,8 +247,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Remove Text Styling -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Uploaded to an unknown Filelink account. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } - Filelink Attachment +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = The file { $filename } was attached as a Filelink. It can be downloaded from the link below. # Template @@ -255,22 +274,27 @@ *[other] I've linked { $count } files to this email: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Learn more about { $lastLink }. - *[other] Learn more about { $firstLinks } and { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Learn more about { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Learn more about { $firstLinks } and { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Password protected link # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = CloudFile Service: +cloud-file-template-service-name = Filelink Service: cloud-file-template-size = Size: cloud-file-template-link = Link: cloud-file-template-password-protected-link = Password Protected Link: @@ -294,3 +318,9 @@ cloud-file-rename-error-with-custom-message-title = Renaming { $filename } on { $provider } Failed # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = { $provider } does not support renaming already uploaded files. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Filelink Attachment Error +cloud-file-attachment-error = Failed to update the Filelink attachment { $filename }, because its local file has been moved or deleted. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Filelink Account Error +cloud-file-account-error = Failed to update the Filelink attachment { $filename }, because its Filelink account has been deleted. diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/messenger.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/messenger.ftl 2022-04-15 07:52:07.000000000 +0000 @@ -188,3 +188,62 @@ .title = Switch to the settings tab spaces-toolbar-button-collapse = .title = Collapse spaces toolbar +spaces-toolbar-button-reveal = + .title = Show the spaces toolbar +spaces-context-new-tab-item = + .label = Open in new tab +spaces-context-new-window-item = + .label = Open in new window +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Switch to { $tabName } +settings-context-open-settings-item = + .label = Open Settings +settings-context-open-account-settings-item = + .label = Open Account Settings +settings-context-open-addons-item = + .label = Open Add-ons and Themes + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Open spaces menu +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [one] One unread message + *[other] { $count } unread messages + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Customise… +spaces-customize-panel-title = Spaces Toolbar Settings +spaces-customize-background-color = Background colour +spaces-customize-icon-color = Button colour +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Selected button background colour +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Selected button colour +spaces-customize-button-restore = Restore Defaults + .accesskey = R +spaces-customize-button-save = Done + .accesskey = D diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:37:19.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -16,15 +16,13 @@ .label = Open details and edit acceptance… openpgp-one-recipient-status-discover = .label = Discover new or updated key - openpgp-one-recipient-status-instruction1 = To send an end-to-end encrypted message to a recipient, you need to obtain their OpenPGP public key and mark it as accepted. openpgp-one-recipient-status-instruction2 = To obtain their public key, import them from email they have sent to you and that includes it. Alternatively, you can try to discover their public key on a directory. - openpgp-key-own = Accepted (personal key) openpgp-key-secret-not-personal = Not usable openpgp-key-verified = Accepted (verified) openpgp-key-unverified = Accepted (unverifed) openpgp-key-undecided = Not accepted (undecided) openpgp-key-rejected = Not accepted (rejected) - +openpgp-key-expired = Expired openpgp-intro = Available public keys for { $key } diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/otr/add-finger.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/otr/add-finger.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Add OTR Key Fingerprint - +otr-add-finger-title = Add OTR Key Fingerprint # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Enter the OTR key fingerprint for { $name }. - otr-add-finger-fingerprint = Fingerprint: otr-add-finger-tooltip-error = Invalid character entered. Only letters ABCDEF and numbers are allowed - otr-add-finger-input = .placeholder = The 40 characters long OTR key fingerprint diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/otr/finger.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/otr/finger.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Close .title = Previously Seen OTR Fingerprints - +otr-finger-title = Previously Seen OTR Fingerprints finger-intro = OTR key fingerprints from previous end-to-end encrypted conversations. - finger-screen-name = .label = Contact finger-verified = .label = Verification Status finger-fingerprint = .label = Fingerprint - finger-remove = .label = Remove Selected - finger-remove-all = .label = Remove All diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/mail/messenger/preferences/preferences.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -116,9 +116,6 @@ .label = Restore Default .accesskey = R default-search-engine = Default Search Engine -add-search-engine = - .label = Add from file - .accesskey = A add-web-search-engine = .label = Add… .accesskey = A @@ -196,6 +193,9 @@ smooth-scrolling-label = .label = Use smooth scrolling .accesskey = m +browsing-gtk-use-non-overlay-scrollbars = + .label = Always show scrollbars + .accesskey = c system-integration-legend = System Integration always-check-default = .label = Always check to see if { -brand-short-name } is the default mail client on startup @@ -320,12 +320,6 @@ .accesskey = o search-handler-table = .placeholder = Filter content types and actions -type-column-label = - .label = Content Type - .accesskey = T -action-column-label = - .label = Action - .accesskey = A type-column-header = Content Type action-column-header = Action save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/en-GB/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/en-GB/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:52:06.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Close Reader View @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Colour Scheme Light aboutReader.toolbar.colorschemedark = Colour Scheme Dark aboutReader.toolbar.colorschemesepia = Colour Scheme Sepia +aboutReader.toolbar.colorschemeauto = Colour Scheme Auto diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/en-GB/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/en-GB/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/toolkit/chrome/global/narrate.properties 2022-04-15 07:52:06.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Listen back = Backwards start = Start stop = Stop +# %S is the keyboard shortcut for the start command +start-label = Start (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Stop (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Forwards speed = Speed selectvoicelabel = Voice: diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/en-GB/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } frame + *[other] { $frames } frames + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } channel + *[other] { $channels } channels + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/en-GB/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/en-GB/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/en-GB/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:20.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/en-GB/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:52:06.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Address Bar: show results during IME composition experimental-features-ime-search-description = An IME (Input Method Editor) is a tool that allows you to enter complex symbols, such as those used in East Asian or Indic written languages, using a standard keyboard. Enabling this experiment will keep the address bar panel open, showing search results and suggestions, while using IME to input text. Note that the IME might display a panel that covers the address bar results, therefore this preference is only suggested for IME not using this type of panel. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name } 100 User-Agent String +experimental-features-firefox-100-description = Make { -brand-short-name } send web sites a User-Agent string that pretends to be { -brand-product-name } version 100. Use this setting to test whether web sites will break when { -brand-short-name } hits a three-digit version number. The real { -brand-product-name } 100 is scheduled to be released in May 2022, so start testing your web sites now! diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/es-AR/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Privacidad: Evento privado calendar-editable-item-privacy-icon-confidential = .alt = Privacidad: Mostrar solamente fecha y hora +calendar-editable-item-recurrence = + .alt = Periódico +calendar-editable-item-recurrence-exception = + .alt = Excepción a la periodicidad calendar-editable-item-todo-icon-task = .alt = Tarea calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/es-AR/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:52:16.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } te ha invitado a: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Guardar +calendar-invitation-panel-accept-button = Sí +calendar-invitation-panel-decline-button = No +calendar-invitation-panel-tentative-button = Quizás +calendar-invitation-panel-reply-status = * Aún no has decidido ni respondido +calendar-invitation-panel-prop-title-when = Cuando: +calendar-invitation-panel-prop-title-location = Ubicación: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Asistentes: +calendar-invitation-panel-prop-title-description = Descripción: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } sí + [DECLINED] { $count } no + [TENTATIVE] { $count } quizás + [NEEDS-ACTION] { $count } pendientes + [TOTAL] { $count } participantes + *[OTHER] { $count } otros + } diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/chat/matrix.properties thunderbird-91.8.1+build1/l10n/es-AR/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/es-AR/chat/matrix.properties 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/chat/matrix.properties 2022-04-15 07:52:14.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S canceló la verificación por la razón: %2$S message.verification.done=Verificación completa. +message.decryptionError=No se pudo descifrar el contenido de este mensaje. Para solicitar claves de cifrado de sus otros dispositivos, haga clic derecho en este mensaje. +message.decrypting=Descifrando... +message.redacted=El mensaje fue modificado. + +# Label in the message context menu +message.action.requestKey=Volver a solicitar claves +message.action.redact=Editar +message.action.report=Informar mensaje +message.action.retry=Reintentar envío +message.action.cancel=Cancelar mensaje + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Se produjo un error al enviar el mensaje "%1$S". diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/aboutdebugging.ftl 2022-03-07 21:37:26.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/aboutdebugging.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -63,7 +63,7 @@ about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Soporte de depuración # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar @@ -108,13 +108,13 @@ # USB section step by step guide about-debugging-setup-usb-step-plug-device = Conectar el dispositivo Android a su equipo. # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = ¿Problemas conectando al dispositivo USB? Solucionar problemas # Network section of the Setup page about-debugging-setup-network = .title = Ubicación de la red # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = ¿Problemas conectando vía ubicación de red? Solucionar problemas # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. @@ -166,11 +166,11 @@ # runtimes. about-debugging-runtime-profile-button2 = Rendimiento del perfil # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = La configuración del navegador no es compatible con Service Workers. Conocer más # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = El navegador conectado tiene una versión antigua ({ $runtimeVersion }). La versión mínima compatible es ({ $minVersion }). Esta es una configuración incompatible y puede causar la falla de DevTools. Actualice el navegador conectado. Resolución de problemas @@ -178,7 +178,7 @@ # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = Esta versión de Firefox no puede depurar Firefox para Android (68). Recomendamos instalar Firefox para Android Nightly en su teléfono para realizar pruebas. Más detalles # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") @@ -224,6 +224,11 @@ # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Eliminar +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Terminar script en segundo plano # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. @@ -247,6 +252,15 @@ # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = ID de extensión +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Script en segundo plano +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = En ejecución +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Detenido # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/compatibility.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/compatibility.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (experimental) compatibility-issue-prefixneeded = (se necesita prefijo) compatibility-issue-deprecated-experimental = (obsoleto, experimental) - compatibility-issue-deprecated-prefixneeded = (obsoleto, se necesita prefijo) compatibility-issue-experimental-prefixneeded = (experimental, se necesita prefijo) compatibility-issue-deprecated-experimental-prefixneeded = (obsoleto, experimental, se necesita prefijo) @@ -43,7 +42,14 @@ [one] { $number } ocurrencia *[other] { $number } ocurrencias } - compatibility-no-issues-found = No se encontraron problemas de compatibilidad. compatibility-close-settings-button = .title = Cerrar ajustes +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Problemas de compatibilidad en: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/netmonitor.properties 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/netmonitor.properties 2022-04-15 07:52:14.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=La cadena “%S” se eliminó del principio del JSON que se muestra a continuación + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Cadena de búsqueda: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=Parámetros de la URL + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Encabezados del pedido: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Encabezados + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=nombre + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=valor + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Cuerpo + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=carga + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Cuerpo del pedido: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Cancelar +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Limpiar + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Eliminar elemento + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Atrás diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/toolbox-options.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/toolbox-options.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Habilitar depuración remota options-enable-remote-tooltip2 = .title = Activar esta opción permitirá depurar esta instancia del navegador de forma remota +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Habilitar los formateadores pesronalizados +options-enable-custom-formatters-tooltip = + .title = Habilitar esta opción permitirá a los sitios definir fomateadores personalizados para los objetos DOM # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Habilitar Service Workers sobre HTTP (cuando esté abierta la caja de herramientas) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/es-AR/devtools/client/webconsole.properties 2022-03-07 21:37:26.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/devtools/client/webconsole.properties 2022-04-15 07:52:14.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=Archivo +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Copiar todos los mensajes +webconsole.menu.copyAllMessages.accesskey=m + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Guardar todos los mensajes en un archivo +webconsole.menu.saveAllMessagesFile.accesskey=v + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/es-AR/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/es-AR/dom/chrome/dom/dom.properties 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/dom/chrome/dom/dom.properties 2022-04-15 07:52:16.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Ingrese una URL. FormValidationInvalidDate=Ingrese una fecha válida. FormValidationInvalidTime=Ingrese una hora válida. +FormValidationInvalidDateTime=Ingrese fecha y hora válidas. +FormValidationInvalidDateMonth=Ingrese un mes válido. +FormValidationInvalidDateWeek=Ingrese una semana válida. FormValidationPatternMismatch=Please match the requested format. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Please match the requested format: %S. diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/es-AR/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/es-AR/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:37:26.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:52:14.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/aboutDialog.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Qué hay de nuevo diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/aboutImport.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/aboutImport.ftl 2022-04-15 07:52:16.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Elegí para importar cuentas, libretas de direcciones, calendarios y otros datos de: import-address-book = Importar archivo de libreta de direcciones import-calendar = Importar archivo de calendario +export-profile = Exportar ## Buttons button-cancel = Cancelar button-back = Atrás button-continue = Continuar +button-export = Exportar ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Importar desde { $app } @@ -26,17 +33,52 @@ profile-file-picker-dir = Seleccionar una carpeta de perfil profile-file-picker-zip = Seleccionar un archivo zip (menor a 2GB) items-pane-title = Seleccionar qué importar -items-pane-desc = Importar de +items-pane-source = Ubicación de la fuente: items-pane-checkbox-accounts = Cuentas y configuración items-pane-checkbox-address-books = Libretas de direcciones items-pane-checkbox-calendars = Calendarios items-pane-checkbox-mail-messages = Mensajes de correo +## Import from address book file steps + +import-from-addr-book-file-desc = Seleccione el tipo de archivo que desea importar: +addr-book-csv-file = Archivo separado por comas o tabulaciones (.csv, .tsv) +addr-book-ldif-file = Archivo LDIF (.ldif) +addr-book-vcard-file = Archivo vCard (.vcf, .vcard) +addr-book-sqlite-file = Base de datos SQLite (.sqlite) +addr-book-mab-file = Archivo de base de datos Mork (.mab) +addr-book-file-picker = Seleccione un archivo de libreta de direcciones +addr-book-csv-field-map-title = Coincidir nombres de campo +addr-book-csv-field-map-desc = Seleccione los campos de la libreta de direcciones correspondientes a los campos de origen. Desmarque los campos que no desea importar. +addr-book-directories-pane-title = Seleccione el directorio al que desea importar: +addr-book-directories-pane-source = Archivo fuente: +addr-book-import-into-new-directory = Crear nueva carpeta + ## Import dialog progress-pane-title = Importando +progress-pane-importing = Importando +progress-pane-exporting = Exportando +progress-pane-finished-desc = Finalizado. progress-pane-restart-desc = Reiniciar para finalizar la importación. error-pane-title = Error error-message-zip-file-too-big = El archivo zip seleccionado tiene más de 2GB. Primero extráigalo y luego impórtelo de la carpeta extraída. error-message-extract-zip-file-failed = Falló la extracción del archivo zip. Extráigalo de forma manual y luego impórtelo de la carpeta extraída. error-message-failed = La importación falló inesperadamente, puede haber más información disponible en la consola de errores. +error-export-failed = La exportación falló inesperadamente, puede haber más información disponible en la consola de errores. + +## element + +csv-first-row-contains-headers = La primera fila contiene nombres de campo +csv-source-field = Campo origen +csv-source-first-record = Primer registro +csv-source-second-record = Segundo registro +csv-target-field = Campo de la libreta de direcciones + +## Export tab + +export-profile-desc = Exportar cuentas de correo, mensajes de correo, libretas de direcciones y configuraciones a un archivo zip. Cuando sea necesario, se puede importar el archivo zip para restaurar el perfil. +export-profile-desc2 = Si su perfil actual tiene más de 2 GB, sugerimos que haga una copia de seguridad usted mismo. +export-open-profile-folder = Abrir carpeta de perfil +export-file-picker = Exportar a un archivo zip +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Nueva libreta de direcciones CardDAV - +carddav-window-title = Nueva libreta de direcciones CardDAV carddav-dialog = .buttonlabelaccept = Continuar .buttonaccesskeyaccept = C - carddav-username-label = .value = Nombre de usuario: .accesskey = U - carddav-location-label = .value = Ubicación: .accesskey = L carddav-location = .default-placeholder = URL o nombre de host del servidor de la libreta de direcciones - carddav-loading = Buscando la configuración… carddav-known-incompatible = Se sabe que { $url } es incompatible con { -brand-short-name }. carddav-connection-error = No se pudo conectar. carddav-none-found = No se encontraron libretas de direcciones para agregar a la cuenta especificada. carddav-already-added = Ya se agregaron todas las libretas de direcciones para la cuenta especificada. - carddav-available-books = Libretas de direcciones disponibles: diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -132,8 +132,8 @@ about-addressbook-details-home-address-header = Dirección personal about-addressbook-details-work-address-header = Dirección laboral about-addressbook-details-other-info-header = Otra información -about-addressbook-prompt-to-save-title = ¿Guardar cambios? -about-addressbook-prompt-to-save = ¿Desea guardar los cambios? +about-addressbook-unsaved-changes-prompt-title = Cambios sin guardar +about-addressbook-unsaved-changes-prompt = ¿Desea guardar los cambios antes de salir de la vista de edición? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:52:16.000000000 +0000 @@ -87,6 +87,13 @@ .tooltiptext = Mostrar el panel de adjuntos ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Ocultar el panel de adjuntos ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key } ) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } adjunto + [one] { $count } adjunto + *[other] { $count } adjuntos + } attachment-area-show = .title = Mostrar el panel de adjuntos ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -242,8 +249,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Eliminar estilo de texto -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Subido a una cuenta Filelink desconocida. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } - Adjunto Filelink +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = El archivo { $filename } fue adjuntado como un Filelink. Puede descargarse desde el enlace siguiente. # Template @@ -256,22 +276,27 @@ *[other] He enlazado { $count } archivos a este correo electrónico: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Conocer más sobre { $lastLink }. - *[other] Conocer más sobre{ $firstLinks } y { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Conocé más sobre { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Conocé más sobre { $firstLinks } y { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Enlace protegido por contraseña # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = Servicio CloudFile: +cloud-file-template-service-name = Servicio Filelink: cloud-file-template-size = Tamaño: cloud-file-template-link = Enlace: cloud-file-template-password-protected-link = Enlace protegido por contraseña: @@ -295,3 +320,9 @@ cloud-file-rename-error-with-custom-message-title = Fallo al renombrar { $filename } en { $provider } # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = { $provider } no aporta renombrar archivos ya subidos. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Error al adjuntar Filelink +cloud-file-attachment-error = Fallo la actualización del adjunto Filelink { $filename } porque el archivo local fue movido o borrado. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Error de cuenta Filelink +cloud-file-account-error = Fallo la actualización del adjunto Filelink { $filename } porque la cuenta Filelink fue borrada. diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/messenger.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/messenger.ftl 2022-04-15 07:52:16.000000000 +0000 @@ -173,7 +173,7 @@ ## Spaces toolbar spaces-toolbar = - .toolbarname = Barra de herramientas Espacios + .toolbarname = Barra de herramientas de Espacios spaces-toolbar-button-mail = .title = Cambiar a la pestaña de Correo spaces-toolbar-button-address-book = @@ -188,3 +188,62 @@ .title = Cambiar a la pestaña de Preferencias spaces-toolbar-button-collapse = .title = Contraer la barra de Espacios +spaces-toolbar-button-reveal = + .title = Mostrar la barra de Espacios +spaces-context-new-tab-item = + .label = Abrir en una nueva pestaña +spaces-context-new-window-item = + .label = Abrir en nueva ventana +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Cambiar a { $tabName } +settings-context-open-settings-item = + .label = Abrir configuración +settings-context-open-account-settings-item = + .label = Abrir configuración de cuenta +settings-context-open-addons-item = + .label = Abrir complementos y temas + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Abrir menú de Espacios +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [one] Un mensaje sin leer + *[other] { $count } mensajes sin leer + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Personalizar… +spaces-customize-panel-title = Configuración de la barra de Espacios +spaces-customize-background-color = Color de fondo +spaces-customize-icon-color = Color del botón +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Color de fondo del botón seleccionado +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Color del botón seleccionado +spaces-customize-button-restore = Restaurar predeterminados + .accesskey = R +spaces-customize-button-save = Listo + .accesskey = L diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:37:26.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -16,15 +16,13 @@ .label = Abrir detalles y editar aceptación… openpgp-one-recipient-status-discover = .label = Descubrir clave nueva o actualizada - openpgp-one-recipient-status-instruction1 = Para enviar un mensaje cifrado de punta a punta un destinatario, debe obtener su clave pública OpenPGP y marcarla como aceptada. openpgp-one-recipient-status-instruction2 = Para obtener la clave pública de ellos, impórtela desde el correo electrónico que le enviaron y eso la incluye. Alternativamente, puede intentar descubrir la clave pública de ellos en un directorio. - openpgp-key-own = Aceptada (clave personal) openpgp-key-secret-not-personal = No utilizable openpgp-key-verified = Aceptada (verificada) openpgp-key-unverified = Aceptada (sin verificar) openpgp-key-undecided = No aceptada (indecisa) openpgp-key-rejected = No aceptada (rechazada) - +openpgp-key-expired = Expirada openpgp-intro = Claves públicas disponibles para { $key } diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/openpgp/openpgp.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/openpgp/openpgp.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/openpgp/openpgp.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/openpgp/openpgp.ftl 2022-04-15 07:52:16.000000000 +0000 @@ -340,6 +340,7 @@ window-locked = La ventana de redacción está bloqueada; enviar cancelado # Strings in mimeDecrypt.jsm mime-decrypt-encrypted-part-attachment-label = Parte del mensaje cifrado +# Strings in mimeDecrypt.jsm mime-decrypt-encrypted-part-concealed-data = Esta es una parte de mensaje cifrado. Tiene que abrirla en una ventana separada haciendo clic en el archivo adjunto. # Strings in keyserver.jsm keyserver-error-aborted = Abortado @@ -488,7 +489,7 @@ delete-external-key-title = Eliminar la clave GnuPG externa delete-external-key-description = ¿Quiere eliminar esta ID de clave GnuPG externa? key-in-use-title = Clave OpenPGP actualmente en uso -delete-key-in-use-description = ¡No se puede proceder! La clave que seleccionó para eliminar está siendo usada por esta identidad. Seleccione una clave diferente o ningua, y vuelva a intentarlo. +delete-key-in-use-description = ¡No se puede proceder! La clave que seleccionó para eliminar está siendo usada por esta identidad. Seleccione una clave diferente o ninguna, y vuelva a intentarlo. revoke-key-in-use-description = ¡No se puede proceder! La clave que seleccionó para revocar está siendo usada por esta identidad. Seleccione una clave diferente o ningua, y vuelva a intentarlo. # Strings used in errorHandling.jsm key-error-key-spec-not-found = La dirección de correo '{ $keySpec }' no puede coincidir con una clave en su llavero. diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/otr/add-finger.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/otr/add-finger.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Agregar huella digital clave OTR - +otr-add-finger-title = Agregar huella digital clave OTR # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Ingrese la huella digital de la clave OTR para { $name }. - otr-add-finger-fingerprint = Huella dactilar: otr-add-finger-tooltip-error = El caracter ingresado no es válido. Solo se permiten letras ABCDEF y números - otr-add-finger-input = .placeholder = Huella dactilar de 40 caracteres de la clave OTR diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/otr/finger.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/otr/finger.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Cerrar .title = Huellas digitales OTR vistas previamente - +otr-finger-title = Huellas digitales OTR vistas previamente finger-intro = Huellas digitales de clave OTR de conversaciones cifradas de punta a punta anteriores. - finger-screen-name = .label = Contacto finger-verified = .label = Estado de la verificación finger-fingerprint = .label = Huella digital - finger-remove = .label = Eliminar seleccionados - finger-remove-all = .label = Eliminar todo diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/mail/messenger/preferences/preferences.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -116,9 +116,6 @@ .label = Restaurar predeterminados .accesskey = R default-search-engine = Buscador predeterminado -add-search-engine = - .label = Agregar desde archivo - .accesskey = A add-web-search-engine = .label = Agregar… .accesskey = A @@ -196,6 +193,9 @@ smooth-scrolling-label = .label = Usar desplazamiento suave .accesskey = m +browsing-gtk-use-non-overlay-scrollbars = + .label = Siempre mostrar barras de desplazamiento + .accesskey = z system-integration-legend = Integración con el sistema always-check-default = .label = Siempre verificar si { -brand-short-name } es el cliente de correo predeterminado al iniciar @@ -320,12 +320,6 @@ .accesskey = o search-handler-table = .placeholder = Filtrar tipos de contenido y acciones -type-column-label = - .label = Tipo de contenido - .accesskey = T -action-column-label = - .label = Acción - .accesskey = A type-column-header = Tipo de contenido action-column-header = Acción save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/es-AR/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/es-AR/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:52:14.000000000 +0000 @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Esquema de color claro aboutReader.toolbar.colorschemedark = Esquema de color oscuro aboutReader.toolbar.colorschemesepia = Esquema de color sepia +aboutReader.toolbar.colorschemeauto = Esquema de color automático diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/es-AR/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/es-AR/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/toolkit/chrome/global/narrate.properties 2022-04-15 07:52:14.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Escuchar back = Atrás start = Inicio stop = Detener +# %S is the keyboard shortcut for the start command +start-label = Iniciar (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Detener (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Adelante speed = Velocidad selectvoicelabel = Voz: diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/es-AR/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } cuadro + *[other] { $frames } cuadros + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } canal + *[other] { $channels } canales + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/es-AR/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/es-AR/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/es-AR/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:27.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-AR/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:52:14.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Barra de direcciones: mostrar los resultados durante la composición IME experimental-features-ime-search-description = Una IME (Input Method Editor) es una herramienta que le permite ingresar símbolos complejos, como los que se usan en los idiomas escritos de Asia oriental o índica, utilizando un teclado estándar. Habilitar este experimento mantendrá abierto el panel de la barra de direcciones, mostrando resultados de búsqueda y sugerencias, mientras se usa IME para ingresar texto. Tenga en cuenta que el IME puede mostrar un panel que cubre los resultados de la barra de direcciones, por lo tanto esta preferencia solo se sugiere para IME que no utilice este tipo de panel. +# Firefox 100 +experimental-features-firefox-100 = + .label = Cadena de agente de usuario de { -brand-product-name } 100 +experimental-features-firefox-100-description = Haz que { -brand-short-name } envie a los sitios web la cadena de agente de usuario que pretenda ser { -brand-product-name } versión 100. Usa esta opción para probar si los sitios webs se romperán cuando { -brand-short-name } llegue a un número de versión de tres digitos. La versión real de { -brand-product-name } 100 está prevista para mayo de 2022, así que ¡empieza a probar ahora! diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/es-ES/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Privacidad: Evento privado calendar-editable-item-privacy-icon-confidential = .alt = Privacidad: Mostrar solo fecha y hora +calendar-editable-item-recurrence = + .alt = Periódico +calendar-editable-item-recurrence-exception = + .alt = Excepción a la periodicidad calendar-editable-item-todo-icon-task = .alt = Tarea calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/chat/imtooltip.properties thunderbird-91.8.1+build1/l10n/es-ES/chat/imtooltip.properties --- thunderbird-91.7.0+build2/l10n/es-ES/chat/imtooltip.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/chat/imtooltip.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,8 +2,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -buddy.username = Nombre de usuario -buddy.account = Cuenta -contact.tags = Etiquetas -otr.tag = Estado OTR -message.status = Mensaje cifrado +buddy.username=Nombre de usuario +buddy.account=Cuenta +contact.tags=Etiquetas + +otr.tag=Estado OTR + +encryption.tag=Estado de cifrado +message.status=Mensaje cifrado diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/chat/matrix.properties thunderbird-91.8.1+build1/l10n/es-ES/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/es-ES/chat/matrix.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/chat/matrix.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,9 +2,257 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -options.connectServer = Servidor -options.connectPort = Puerto -chatRoomField.room = _Sala -tooltip.displayName = Nombre mostrado -tooltip.timespan = hace %S -tooltip.lastActive = Última actividad +# LOCALIZATION NOTE (matrix.usernameHint): +# This is displayed inside the accountUsernameInfoWithDescription +# string defined in imAccounts.properties when the user is +# configuring a Matrix account. +matrix.usernameHint=Matrix ID + +# LOCALIZATION NOTE (options.*): +# These are the protocol specific options shown in the account manager and +# account wizard windows. +options.saveToken=Guardar el token de acceso +options.deviceDisplayName=Nombre para mostrar del dispositivo +options.homeserver=Servidor + +options.backupPassphrase=Contraseña de la copia de seguridad de la clave + +# LOCALIZATION NOTE (options.encryption.*): +# These are strings used to build the status information of the encryption +# storage, shown in the account manager. %S is one of the statuses and the +# strings are combined with a pipe (|) between. +options.encryption.enabled=Funciones criptográficas: %S +options.encryption.secretStorage=Almacenamiento secreto: %S +options.encryption.keyBackup=Copia de seguridad de la clave de cifrado: %S +options.encryption.crossSigning=Firma cruzada: %S +options.encryption.statusOk=ok +options.encryption.statusNotOk=no está listo +options.encryption.needBackupPassphrase=Introduce la frase de contraseña de tu clave de respaldo en las opciones de protocolo. +options.encryption.setUpSecretStorage=Para configurar el almacenamiento secreto, utilice otro cliente y luego introduzca la frase de contraseña de la clave de respaldo generada en la pestaña "General". +options.encryption.setUpBackupAndCrossSigning=Para activar las copias de seguridad de la clave de cifrado y la firma cruzada, introduzca su frase de contraseña de la clave de respaldo en la pestaña "General" o verifique la identidad de una de las sesiones a continuación. +# %1$S is the session ID, %2$S is the session display name +options.encryption.session=%1$S (%2$S) + +# LOCALIZATION NOTE (connection.*): +# These will be displayed in the account manager in order to show the progress +# of the connection. +# (These will be displayed in account.connection.progress from +# accounts.properties, which adds … at the end, so do not include +# periods at the end of these messages.) +connection.requestAuth=Esperando su autorización +connection.requestAccess=Finalizando autentificación + +# LOCALIZATION NOTE (connection.error.*): +# These will show in the account manager if an error occurs during the +# connection attempt. +connection.error.noSupportedFlow=El servidor no ofrece ningún flujo de inicio de sesión compatible. +connection.error.authCancelled=Ha cancelado el proceso de autorización. +connection.error.sessionEnded=La sesión se ha cerrado. +connection.error.serverNotFound=No se ha podido identificar el servidor Matrix para la cuenta Matrix indicada. + +# LOCALIZATION NOTE (chatRoomField.*): +# These are the name of fields displayed in the 'Join Chat' dialog +# for Matrix accounts. +# The _ character won't be displayed; it indicates the next +# character of the string should be used as the access key for this +# field. +chatRoomField.room=_Sala + +# LOCALIZATION NOTE (tooltip.*): +# These are the descriptions given in a tooltip with information received +# from the "User" object. +# The human readable name of the user. +tooltip.displayName=Nombre mostrado +# %S is the timespan elapsed since the last activity. +tooltip.timespan=hace %S +tooltip.lastActive=Última actividad + +# LOCALIZATION NOTE (powerLevel.*): +# These are the string representations of different standard power levels and strings. +# %S are one of the power levels, Default/Moderator/Admin/Restricted/Custom. +powerLevel.default=Predeterminado +powerLevel.moderator=Moderador +powerLevel.admin=Administrador +powerLevel.restricted=Restringido +powerLevel.custom=Personalizado +# %1$S is the power level name +# %2$S is the power level number +powerLevel.detailed=%1$S (%2$S) +powerLevel.defaultRole=Rol predeterminado: %S +powerLevel.inviteUser=Invitar usuarios: %S +powerLevel.kickUsers=Expulsar usuarios: %S +powerLevel.ban=Bloquear usuarios: %S +powerLevel.roomAvatar=Cambiar avatar de sala: %S +powerLevel.mainAddress=Cambiar dirección principal de la sala: %S +powerLevel.history=Cambiar la visibilidad del historial: %S +powerLevel.roomName=Cambiar nombre de la sala: %S +powerLevel.changePermissions=Cambiar permisos: %S +powerLevel.server_acl=Enviar eventos m.room.server_acl: %S +powerLevel.upgradeRoom=Actualizar la sala: %S +powerLevel.remove=Eliminar mensajes: %S +powerLevel.events_default=Eventos predeterminados: %S +powerLevel.state_default=Cambiar la configuración: %S +powerLevel.encryption=Activar el cifrado de la sala: %S +powerLevel.topic=Establecer el tema de la sala: %S + +# LOCALIZATION NOTE (detail.*): +# These are the string representations of different matrix properties. +# %S will typically be strings with the actual values. +# Example placeholder: "Foo bar" +detail.name=Nombre: %S +# Example placeholder: "My first room" +detail.topic=Tema: %S +# Example placeholder: "5" +detail.version=Versión de la sala: %S +# Example placeholder: "#thunderbird:mozilla.org" +detail.roomId=RoomID: %S +# %S are all admin users. Example: "@foo:example.com, @bar:example.com" +detail.admin=Administrador: %S +# %S are all moderators. Example: "@lorem:mozilla.org, @ipsum:mozilla.org" +detail.moderator=Moderador: %S +# Example placeholder: "#thunderbird:matrix.org" +detail.alias=Alias: %S +# Example placeholder: "can_join" +detail.guest=Acceso de invitado: %S +# This is a heading, followed by the powerLevel.* strings +detail.power=Niveles de poder: + +# LOCALIZATION NOTE (command.*): +# These are the help messages for each command, the %S is the command name +# Each command first gives the parameter it accepts and then a description of +# the command. +command.ban=%S <userId> [<motivo>]: Excluir de la sala al usuario con el userId con un mensaje opcional de motivo. Requiere permiso para prohibir usuarios. +command.invite=%S <userId>: Invitar usuario a la sala. +command.kick=%S & lt;userId > [<motivo& gt;]: Echar al usuario con el userId de la sala con un mensaje de motivo opcional. Requiere permiso para echar a usuarios. +command.nick=%S <nombre_para_mostrar>: Cambiar su nombre para mostrar. +command.op=%S <userId> [<nivel de poder>]: Define el nivel de poder del usuario. Escribir un valor entero, Usuario: 0, Moderador: 50 y Administrador: 100. El valor predeterminado será de 50 si no se indica. Requiere permiso para cambiar los niveles de poder de los miembros. No funciona en administradores que no sean usted mismo. +command.deop=%S <userId>: Restablecer el usuario al nivel de poder 0 (Usuario). Requiere permiso para cambiar los niveles de poder de los miembros. No funciona en otros administradores que no sea usted mismo. +command.leave=%S: Salir de la sala actual. +command.topic=%S <topic>: Establecer el tema de la sala. Requiere permisos para cambiar el tema de la sala. +command.unban=%S <userId>: Eliminar la prohibición a un usuario que está prohibido en la sala. Requiere permiso para prohibir usuarios. +command.visibility=%S [<visibility>]: Establece la visibilidad de la sala actual en el directorio actual del servidor de inicio. Escribir un valor entero, Privado: 0 y Público: 1. El valor predeterminado, será privado (0) si no se proporciona ningún argumento. Requiere permiso para cambiar la visibilidad de la sala. +command.guest=%S <acceso invitado> <visibilidad de historial>: Establecer el acceso y la visibilidad del historial de la sala actual para los usuarios invitados. Introducir dos valores enteros, el primero para el acceso de los invitados (no permitido: 0 y permitido: 1) y el segundo para la visibilidad del historial (no visible: 0 y visible: 1). Requiere permiso para cambiar la visibilidad del historial. +command.roomname=%S <nombre>: Establecer el nombre de la sala. Requiere permisos para cambiar el nombre de la sala. +command.detail=%S: Mostrar los detalles de la sala. +command.addalias=%S <alias>: Crear un alias para la sala. Se esperaba un alias de la sala de la forma '#localname:domain'. Requiere permiso para añadir alias. +command.removealias=%S <alias>: Eliminar el alias de la sala. Se esperaba un alias de la sala de la forma '#localname:domain'. Requiere permiso para eliminar alias. +command.upgraderoom=%S <newVersion>: Actualizar la sala a determinada versión. Requiere permiso para actualizar la sala. +command.me=%S <acción a ejecutar>: Realizar una acción. +command.msg=%S <userId> <mensaje>: Enviar un mensaje directo al usuario dado. +command.join=%S <roomId>: Unirse a la sala dada. + +# LOCALIZATION NOTE (message.*): +# These are shown as system messages in the conversation. +# %S is the reason string for the particular action. +# Used within context of ban, kick and withdrew invite. +message.reason=Motivo: %S. + +# LOCALIZATION NOTE (message.*): +# These are shown as system messages in the conversation. +# %1$S is the name of the user who banned. +# %2$S is the name of the user who got banned. +message.banned=%1$S ha bloqueado a %2$S. +# Same as message.banned but with a reason. +# %3$S is the reason the user was banned. +message.bannedWithReason=%1$S bloqueó a %2$S. Razón: %3$S +# %1$S is the name of the user who accepted the invitation. +# %2$S is the name of the user who sent the invitation. +message.acceptedInviteFor=%1$S aceptó la invitación para %2$S. +# %S is the name of the user who accepted an invitation. +message.acceptedInvite=$S aceptó una invitación. +# %1$S is the name of the user who invited. +# %2$S is the name of the user who got invited. +message.invited=%1$S invitó a %2$S. +# %1$S is the name of the user who changed their display name. +# %2$S is the old display name. +# %3$S is the new display name. +message.displayName.changed=%1$S cambió su nombre mostrado de %2$S a %3$S. +# %1$S is the name of the user who set their display name. +# %2$S is the newly set display name. +message.displayName.set=%1$S estableció su nombre a mostrar a %2$S. +# %1$S is the name of the user who removed their display name. +# %2$S is the old display name which has been removed. +message.displayName.remove=%1$S eliminó su nombre a mostrar %2$S. +# %S is the name of the user who has joined the room. +message.joined=%S se ha unido a la sala. +# %S is the name of the user who has rejected the invitation. +message.rejectedInvite=%S ha rechazado la invitación. +# %S is the name of the user who has left the room. +message.left=%S ha abandonado la sala. +# %1$S is the name of the user who unbanned. +# %2$S is the name of the user who got unbanned. +message.unbanned=%1$S desbloqueó a %2$S. +# %1$S is the name of the user who kicked. +# %2$S is the name of the user who got kicked. +message.kicked=%1$S expulsó a %2$S. +# Same as message.kicked but with a third parameter for the reason. +# %3$S is the reason for the kick. +message.kickedWithReason=%1$S expulsado %2$S. Motivo: %3$S +# %1$S is the name of the user who withdrew invitation. +# %2$S is the name of the user whose invitation has been withdrawn. +message.withdrewInvite=%1$S retiró la invitación de %2$S. +# Same as message.withdrewInvite but with a third paramter for the reason. +# %3$S is the reason the invite was withdrawn. +message.withdrewInviteWithReason=%1$S retiró la invitación de %2$S. Motivo: %3$S +# %S is the name of the user who has removed the room name. +message.roomName.remove=%S eliminó el nombre de la sala. +# %1$S is the name of the user who changed the room name. +# %2$S is the new room name. +message.roomName.changed=%1$S cambió el nombre de la sala a %2$S. +# %1$S is the name of the user who changed the power level. +# %2$S is a list of "message.powerLevel.fromTo" strings representing power level changes separated by commas +# power level changes, separated by commas if there are multiple changes. +message.powerLevel.changed=%1$S cambió el nivel de poder de %2$S. +# %1$S is the name of the target user whose power level has been changed. +# %2$S is the old power level. +# %2$S is the new power level. +message.powerLevel.fromTo=%1$S de %2$S a %3$S +# %S is the name of the user who has allowed guests to join the room. +message.guest.allowed=%S ha permitido que los invitados se unan a la sala. +# %S is the name of the user who has prevented guests to join the room. +message.guest.prevented=%S ha evitado que invitados se unieran a la sala. +# %S is the name of the user who has made future room history visible to anyone. +message.history.anyone=%S hizo que el historial futuro de la sala sea visible para cualquiera. +# %S is the name of the user who has made future room history visible to all room members. +message.history.shared=%S hizo que el historial futuro de la sala sea visible para todos los miembros de la sala. +# %S is the name of the user who has made future room history visible to all room members, from the point they are invited. +message.history.invited=%S hizo que el historial futuro de la sala sea visible para todos los miembros de la sala desde el momento en que sean invitados. +# %S is the name of the user who has made future room history visible to all room members, from the point they joined. +message.history.joined=%S hizo que el historial futuro de la sala sea visible para todos los miembros de la sala desde el momento en que se unieron. +# %1$S is the name of the user who changed the address. +# %2$S is the old address. +# %3$S is the new address. +message.alias.main=%1$S estableció la dirección principal para esta sala de %2$S a %3$S. +# %1$S is the name of the user who added the address. +# %2$S is a comma delimited list of added addresses. +message.alias.added=%1$S añadió %2$S como dirección alternativa para esta sala. +# %1$S is the name of the user who removed the address. +# %2$S is a comma delimited list of removed addresses. +message.alias.removed=%1$S eliminó %2$S como dirección alternativa para esta sala. +# %1$S is the name of the user that edited the alias addresses. +# %2$S is a comma delimited list of removed addresses. +# %3$S is a comma delmited list of added addresses. +message.alias.removedAndAdded=%1$S eliminó %2$S y añadió %3$S como dirección para esta sala. +message.spaceNotSupported=Esta sala es un espacio, lo que no está soportado. +message.encryptionStart=Los mensajes en esta conversación ahora están cifrados de extremo a extremo. +# %1$S is the name of the user who sent the verification request. +# %2$S is the name of the user that is receiving the verification request. +message.verification.request2=%1$S quiere verificar a %2$S. +# %1$S is the name of the user who cancelled the verification request. +# %2$S is the reason given why the verification was cancelled. +message.verification.cancel2=%1$S canceló la verificación por la razón: %2$S +message.verification.done=Verificación completada. +message.decryptionError=No se pudo descifrar el contenido de este mensaje. Para solicitar claves de cifrado de sus otros dispositivos, haga clic en este mensaje con el botón derecho. +message.decrypting=Descifrando... +message.redacted=El mensaje fue redactado. + +# Label in the message context menu +message.action.requestKey=Volver a solicitar claves +message.action.redact=Redactar +message.action.report=Reportar mensaje +message.action.retry=Reintentar envío +message.action.cancel=Cancelar mensaje + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Ha ocurrido un error mientras se enviaba su mensaje "%1$S". diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/chat/twitter.properties thunderbird-91.8.1+build1/l10n/es-ES/chat/twitter.properties --- thunderbird-91.7.0+build2/l10n/es-ES/chat/twitter.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/chat/twitter.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,53 +2,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -twitter.protocolName = Twitter -error.tooLong = El estado supera 140 caracteres. -error.general = Ha ocurrido un error %1$S al enviar: %2$S -error.retweet = Ha ocurrido un error %1$S al retuitear: %2$S -error.delete = Ha ocurrido un error %1$S al eliminar: %2$S -error.like = Ha ocurrido un error %1$S al indicar Me gusta: %2$S -error.unlike = Ha ocurrido un error %1$S al eliminar Me gusta: %2$S -error.descriptionTooLong = La descripción supera la longitud máxima (160 caracteres), se ha truncado automáticamente a: %S. -timeline = cronología de %S -action.copyLink = Copiar enlace a tuit -action.retweet = Retuitear -action.reply = Responder -action.delete = Eliminar -action.follow = Seguir a %S -action.stopFollowing = Dejar de seguir a %S -action.like = Me gusta -action.unlike = Eliminar Me gusta -event.follow = Ya está siguiendo a %S. -event.unfollow = Ya no sigue a %S. -event.followed = %S le está siguiendo. -event.deleted = Ha eliminado este tuit: "%S". -replyingToStatusText = Respondiendo a: %S -connection.initAuth = Iniciando proceso de identificación -connection.requestAuth = Esperando su autorización -connection.requestAccess = Finalizando identificación -connection.requestTimelines = Solicitando cronología del usuario -connection.error.userMismatch = Discordancia en el nombre de usuario. -connection.error.failedToken = No se ha podido conseguir el token de la solicitud. -connection.error.authCancelled = Ha cancelado el proceso de autorización. -connection.error.authFailed = No se ha podido conseguir autorización. -connection.error.noNetwork = No hay conexión de red disponible. -authPrompt = Conceder permiso para usar su cuenta Twitter -options.track = Palabras clave vigiladas -tooltip.created_at = Usuario desde -tooltip.location = Dirección -tooltip.lang = Idioma -tooltip.time_zone = Zona horaria -tooltip.url = Página de inicio -tooltip.protected = Tiene sus tuits protegidos -tooltip.following = Actualmente siguiendo a -tooltip.name = Nombre -tooltip.description = Descripción -tooltip.friends_count = Siguiendo a -tooltip.statuses_count = Tuits -tooltip.followers_count = Seguidores -tooltip.listed_count = Listado -yes = Sí -no = No -command.follow = %S <nombreusuario>[ <nombreusuario>]*: comienza a seguir a uno o varios usuarios. -command.unfollow = %S <nombreusuario>[ <nombreusuario>]*: deja de seguir a uno o varios usuarios. +# LOCALIZATION NOTE (twitter.protocolName) +# This name is used whenever the name of the protocol is shown. +twitter.protocolName=Twitter + +twitter.disabled=Twitter ya no está disponible debido a que Twitter deshabilitó su protocolo de transmisión. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/aboutdebugging.ftl 2022-03-07 21:37:33.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/aboutdebugging.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Depuración - Configuración - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Depuración - Tiempo de ejecución / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Este { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Configuración - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB habilitado - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB deshabilitado - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Conectado # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Desconectado - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = No se han encontrado dispositivos - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Conectar - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Conectando... - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Falló la conexión - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = La conexión todavía está pendiente, compruebe si hay mensajes en el navegador de destino - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = La conexión ha caducado - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Esperando al navegador... - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Desconectado - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Asistencia de depuración - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Icono de Ayuda - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Actualizar dispositivos @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Configuración - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Configure el método de conexión con el que desea depurar remotamente su dispositivo. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Usa { about-debugging-this-firefox-runtime-name } para depurar extensiones y service workers en esta versión de { -brand-shorter-name }. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Conectar un dispositivo - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Si habilita esta opción, se descargarán y agregarán los componentes de depuración necesarios de Android USB para { -brand-shorter-name }. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = Habilitar dispositivos USB - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = Deshabilitar dispositivos USB - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Actualizando... - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Habilitado about-debugging-setup-usb-status-disabled = Deshabilitado about-debugging-setup-usb-status-updating = Actualizando... - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Activar menú de desarrollador en su dispositivo Android. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Activar depuración USB en el menú de desarrollador de Android. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Activar depuración USB en Firefox en el dispositivo Android. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Conectar el dispositivo Android a su equipo. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = ¿Problemas de conexión al dispositivo USB? Solucionar problemas - # Network section of the Setup page about-debugging-setup-network = .title = Ubicación de red - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = ¿Problemas de conexión a través de la ubicación de la red? Solucionar problemas - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Agregar - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = No se han añadido ubicaciones de red. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Servidor - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Eliminar - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = El servidor no es válido “{ $host-value }”. El formato esperado es "nombreDeServidor:numeroDePuerto". - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Procesos - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Rendimiento del perfil - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = La configuración de su navegador no es compatible con Service Workers. Saber más - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = El navegador conectado tiene una versión antigua ({ $runtimeVersion }). La versión mínima compatible es ({ $minVersion }). Ésta es una configuración incompatible y puede hacer que las herramientas de desarrollo fallen. Por favor, actualice el navegador conectado. Resolución de problemas - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = Esta versión de Firefox no puede depurar Firefox para Android (68). Recomendamos instalar Firefox para Android Nightly en su teléfono para realizar pruebas. Más detalles - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = El navegador conectado es más reciente ({ $runtimeVersion }, buildID { $runtimeID }) que su { -brand-shorter-name } ({ $localVersion }, buildID { $localID }). Ésta es una configuración incompatible y puede hacer que las herramientas de desarrollo fallen. Por favor actualice Firefox. Resolución de problemas - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Desconectar - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Activar solicitud de conexión - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Desactivar solicitud de conexión - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Analizador - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Nada todavía. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Inspeccionar - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Cargar complemento temporal... - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = Hubo un error durante la instalación del complemento temporal. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Recargar - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Eliminar - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Terminar secuencia de comandos en segundo plano # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Selecciona el archivo manifest.json o .xpi/.zip - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Esta WebExtension tiene un ID temporal. Saber más - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = URL del manifiesto - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = UUID interno - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Ubicación - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = ID de la extensión - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Secuencia de comandos en segundo plano +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = En ejecución +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Detenido # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push .disabledTitle = El Service Worker Push está actualmente desactivado para el modo multiproceso de { -brand-shorter-name } - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Inicio .disabledTitle = El inicio de Service Worker está actualmente desactivado para el modo multiproceso de { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Eliminar registro - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Escuchando eventos fetch - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = No se están escuchando eventos fetch - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = En ejecución - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Detenido - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Registrando - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Ámbito - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Servicio Push - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = La inspección de Service Worker está actualmente desactivada para el modo multiproceso de { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = La pestaña no está completamente cargada y no se puede inspeccionar - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Proceso principal - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Proceso principal para el navegador de destino - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Caja de herramientas de multiproceso - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Proceso principal y procesos de contenido para el navegador de destino - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Cerrar mensaje - # Label text used for the error details of message component. about-debugging-message-details-label-error = Detalles del error - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Detalles de la advertencia - # Label text used for default state of details of message component. about-debugging-message-details-label = Detalles diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/compatibility.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/compatibility.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -42,7 +42,14 @@ [one] { $number } ocurrencia *[other] { $number } ocurrencias } - compatibility-no-issues-found = No se encontraron problemas de compatibilidad. compatibility-close-settings-button = .title = Cerrar ajustes +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Problemas de compatibilidad en: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/debugger.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/debugger.properties 2022-04-15 07:52:23.000000000 +0000 @@ -642,6 +642,16 @@ ignoreContextItem.unignore=Dejar de ignorar fuente ignoreContextItem.unignore.accesskey=U +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Ignorar línea +ignoreContextItem.ignoreLine.accesskey=l + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Dejar de ignorar línea +ignoreContextItem.unignoreLine.accesskey=n + # LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated # with the ignore lines context menu item ignoreContextItem.ignoreLines=Ignorar líneas diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/netmonitor.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/netmonitor.properties 2022-04-15 07:52:23.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=La cadena “%S” se eliminó del inicio del JSON que se muestra a continuación + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Cadena de la consulta: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=Parámetros de la URL + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Cabeceras de la petición: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Cabeceras + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=nombre + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=valor + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Cuerpo + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=contenido + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Cuerpo de la petición: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Cancelar +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Limpiar + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Eliminar elemento + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Atrás diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/toolbox.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/toolbox.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Desactivar la ocultación automática de ventanas emergentes +toolbox-meatball-menu-pseudo-locale-accented = Activar idioma “acentuado” +toolbox-meatball-menu-pseudo-locale-bidi = Activar idioma “bidi” ## diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/toolbox-options.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/toolbox-options.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Activar depuración remota options-enable-remote-tooltip2 = .title = Activar esta opción permitirá depurar esta instancia del navegador de forma remota +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Activar formateadores personalizados +options-enable-custom-formatters-tooltip = + .title = Activar esta opción permite que los sitios definan formateadores personalizados para objetos DOM # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Activar service workers bajo HTTP (si la caja de herramientas está abierta) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/es-ES/devtools/client/webconsole.properties 2022-03-07 21:37:33.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/devtools/client/webconsole.properties 2022-04-15 07:52:23.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=Archivo +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Copiar todos los mensajes +webconsole.menu.copyAllMessages.accesskey=m + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Guardar todos los mensajes en un archivo +webconsole.menu.saveAllMessagesFile.accesskey=v + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/es-ES/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/es-ES/dom/chrome/dom/dom.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/dom/chrome/dom/dom.properties 2022-04-15 07:52:24.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Introduzca una URL. FormValidationInvalidDate=Introduzca una fecha válida. FormValidationInvalidTime=Introduzca una hora válida. +FormValidationInvalidDateTime=Introduzca una fecha y hora válida. +FormValidationInvalidDateMonth=Por favor, introduzca un mes válido. +FormValidationInvalidDateWeek=Por favor, introduzca una semana válida. FormValidationPatternMismatch=Ajústese al formato solicitado. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Ajústese al formato solicitado: %S. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/browser/appExtensionFields.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/browser/appExtensionFields.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/browser/appExtensionFields.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/browser/appExtensionFields.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -5,6 +5,9 @@ ## Theme names and descriptions used in the Themes panel in about:addons +# "Auto" is short for automatic. It can be localized without limitations. +extension-default-theme-name-auto = Tema del sistema — Automático +extension-default-theme-description = Seguir la configuración del sistema operativo para botones, menús y ventanas. extension-thunderbird-compact-light-name = Claro extension-thunderbird-compact-light-description = Un tema con un esquema de color claro. extension-thunderbird-compact-dark-name = Oscuro diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/AccountManager.dtd thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/AccountManager.dtd --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/AccountManager.dtd 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/AccountManager.dtd 2022-04-15 07:52:23.000000000 +0000 @@ -2,13 +2,10 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - - - + @@ -25,9 +22,16 @@ - + - + diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/addons.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/addons.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,133 +2,247 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at http://mozilla.org/MPL/2.0/. -xpinstallPromptMessage = %S ha evitado que este sitio le solicite instalar software en su equipo. -xpinstallPromptMessage.header = ¿Permitir a %S instalar un complemento? -xpinstallPromptMessage.message = Está intentando instalar un complemento desde %S. Asegúrese de que confía en este sitio antes de continuar. -xpinstallPromptMessage.header.unknown = ¿Permitir a un sitio desconocido instalar un complemento? -xpinstallPromptMessage.message.unknown = Está intentando instalar un complemento desde un sitio desconocido. Asegúrese de que confía en este sitio antes de continuar. -xpinstallPromptMessage.learnMore = Más información sobre la instalación segura de complementos -xpinstallPromptMessage.dontAllow = No permitir -xpinstallPromptMessage.dontAllow.accesskey = N -xpinstallPromptMessage.neverAllow = No permitir nunca -xpinstallPromptMessage.neverAllow.accesskey = o -xpinstallPromptMessage.install = Continuar con la instalación -xpinstallPromptMessage.install.accesskey = C - -xpinstallDisabledMessageLocked = La instalación de software ha sido desactivada por su administrador de sistema. -xpinstallDisabledMessage = La instalación de software está actualmente desactivada. Pulse Activar y vuelva a intentarlo. -xpinstallDisabledButton = Activar -xpinstallDisabledButton.accesskey = A - -addonInstallBlockedByPolicy = %1$S (%2$S) está bloqueado por su administrador del sistema. %3$S - -addonDownloadingAndVerifying = Descargando y verificando complemento…;Descargando y verificando #1 complementos… -addonDownloadVerifying = Verificando - -addonInstall.unsigned = (No verificado) -addonInstall.cancelButton.label = Cancelar -addonInstall.cancelButton.accesskey = C -addonInstall.acceptButton2.label = Añadir -addonInstall.acceptButton2.accesskey = A - -addonConfirmInstall.message = Este sitio quiere instalar un complemento en #1:;Este sitio quiere instalar #2 complementos en #1: -addonConfirmInstallUnsigned.message = Precaución: este complemento desea instalar un complemento no verificado en #1. Continúe bajo su responsabilidad.;Precaución: este complemento desea instalar #2 complementos no verificados en #1. Continúe bajo su responsabilidad. - -addonConfirmInstallSomeUnsigned.message = ;Precaución: este sitio desea instalar #2 complementos en #1, algunos de los cuales no están verificados. Continúe bajo su responsabilidad. - -addonInstalled = %S ha sido instalado con éxito. -addonsGenericInstalled = #1 complemento ha sido instalado con éxito.;#1 complementos han sido instalados con éxito. - -addonInstallError-1 = El complemento no ha podido descargarse por un fallo de conexión. -addonInstallError-2 = Este complemento no se ha podido instalar porque no coincide con el complemento %1$S esperado. -addonInstallError-3 = El complemento descargado desde este sitio no ha podido instalarse porque parece estar dañado. -addonInstallError-4 = %2$S no ha podido ser instalado porque %1$S no puede modificar el archivo requerido. -addonInstallError-5 = %1$S ha evitado que este sitio instale un complemento no verificado. -addonLocalInstallError-1 = Este complemento no se ha podido instalar por un fallo del sistema de archivos. -addonLocalInstallError-2 = Este complemento no se ha podido instalar porque no coincide con el complemento %1$S esperado. -addonLocalInstallError-3 = Este complemento no se ha podido instalar porque parece estar dañado. -addonLocalInstallError-4 = %2$S no ha podido ser instalado porque %1$S no puede modificar el archivo requerido. -addonLocalInstallError-5 = Este complemento ha podido ser instalado porque no ha sido verificado. - -addonInstallErrorIncompatible = %3$S no ha podido ser instalado porque no es compatible con %1$S %2$S. - -addonInstallErrorBlocklisted = %S no ha podido ser instalado porque tiene un alto riesgo de causar problemas de estabilidad o seguridad. - -webextPerms.header = ¿Añadir %S? - -webextPerms.experimentWarning = Los complementos maliciosos pueden robar su información privada o comprometer su equipo. Instale este complemento únicamente si confía en el origen. - -webextPerms.add.label = Añadir -webextPerms.add.accessKey = A -webextPerms.cancel.label = Cancelar -webextPerms.cancel.accessKey = C - -webextPerms.sideloadMenuItem = %1$S añadido a %2$S - -webextPerms.sideloadHeader = %S añadido -webextPerms.sideloadText2 = Otro programa en su equipo ha instalado un complemento que puede afectar a su navegador. Revise los permisos que solicita este complemento y elija Activar o Cancelar (para dejarlo desactivado). -webextPerms.sideloadTextNoPerms = Otro programa en su equipo ha instalado un complemento que puede afectar a su navegador. Elija Activar o Cancelar (para dejarlo desactivado). - -webextPerms.sideloadEnable.label = Activar -webextPerms.sideloadEnable.accessKey = v -webextPerms.sideloadCancel.label = Cancelar -webextPerms.sideloadCancel.accessKey = C - -webextPerms.updateMenuItem = %S requiere nuevos permisos - -webextPerms.updateAccept.label = Actualizar -webextPerms.updateAccept.accessKey = U - -webextPerms.optionalPermsHeader = %S solicita permisos adicionales. -webextPerms.optionalPermsListIntro = Quiere: -webextPerms.optionalPermsAllow.label = Permitir -webextPerms.optionalPermsAllow.accessKey = P -webextPerms.optionalPermsDeny.label = Denegar -webextPerms.optionalPermsDeny.accessKey = D - -webextPerms.description.accountsFolders = Crear, renombrar o eliminar sus carpetas de cuentas de correo -webextPerms.description.addressBooks = Leer y modificar sus libretas de direcciones y contactos -webextPerms.description.bookmarks = Leer y modificar marcadores -webextPerms.description.browserSettings = Leer y modificar la configuración del navegador -webextPerms.description.browsingData = Limpiar el historial de navegación reciente, las cookies y datos relacionados -webextPerms.description.clipboardRead = Obtener datos del portapapeles -webextPerms.description.clipboardWrite = Enviar datos al portapapeles -webextPerms.description.compose = Leer y modificar sus mensajes de correo mientras los redacta y envía -webextPerms.description.devtools = Extender las herramientas de desarrollador para acceder a sus datos en las pestañas abiertas -webextPerms.description.dns = Acceder a la información de la dirección IP y el nombre de equipo -webextPerms.description.downloads = Descargar archivos y leer y modificar el historial de descargas del navegador -webextPerms.description.downloads.open = Abrir archivos descargados en su equipo -webextPerms.description.experiment = Tener acceso completo y sin restricciones a %S y a su equipo. -webextPerms.description.find = Leer el texto de todas las pestañas abiertas -webextPerms.description.geolocation = Acceder a su ubicación -webextPerms.description.history = Acceder al historial de navegación -webextPerms.description.management = Monitorizar el uso de extensiones y administrar temas -webextPerms.description.messagesRead = Lea sus mensajes de correo y márquelos o etiquételos -webextPerms.description.nativeMessaging = Intercambiar mensajes con otros programas distintos de %S -webextPerms.description.notifications = Mostrarle notificaciones -webextPerms.description.pkcs11 = Proporcionar servicios de autenticación criptográfica -webextPerms.description.privacy = Leer y modificar la configuración de privacidad -webextPerms.description.proxy = Controlar la configuración del proxy del navegador -webextPerms.description.sessions = Acceder a las pestañas cerradas recientemente -webextPerms.description.tabs = Acceder a las pestañas del navegador -webextPerms.description.tabHide = Ocultar y mostrar las pestañas del navegador -webextPerms.description.topSites = Acceder al historial de navegación -webextPerms.description.unlimitedStorage = Guardar una cantidad ilimitada de datos en el lado del cliente -webextPerms.description.webNavigation = Acceder a la actividad del navegador durante la navegación - -webextPerms.hostDescription.allUrls = Acceder a sus datos de todos los sitios web - -webextPerms.hostDescription.wildcard = Acceder a sus datos de sitios en el dominio %S - -webextPerms.hostDescription.tooManyWildcards = Acceder a sus datos en #1 dominio más;Acceder a sus datos en #1 dominios más - -webextPerms.hostDescription.oneSite = Acceder a sus datos de %S - -webextPerms.hostDescription.tooManySites = Acceder a sus datos en #1 sitio más;Acceder a sus datos en #1 sitios más - -webext.defaultSearch.description = %1$S quiere cambiar su buscador predeterminado de %2$S a %3$S. ¿Es correcto? -webext.defaultSearchYes.label = Sí -webext.defaultSearchYes.accessKey = S -webext.defaultSearchNo.label = No -webext.defaultSearchNo.accessKey = N - +xpinstallPromptMessage=%S ha evitado que este sitio le solicite instalar software en su equipo. +# LOCALIZATION NOTE (xpinstallPromptMessage.header) +# The string contains the hostname of the site the add-on is being installed from. +xpinstallPromptMessage.header=¿Permitir a %S instalar un complemento? +xpinstallPromptMessage.message=Está intentando instalar un complemento desde %S. Asegúrese de que confía en este sitio antes de continuar. +xpinstallPromptMessage.header.unknown=¿Permitir a un sitio desconocido instalar un complemento? +xpinstallPromptMessage.message.unknown=Está intentando instalar un complemento desde un sitio desconocido. Asegúrese de que confía en este sitio antes de continuar. +xpinstallPromptMessage.learnMore=Más información sobre la instalación segura de complementos +xpinstallPromptMessage.dontAllow=No permitir +xpinstallPromptMessage.dontAllow.accesskey=N +xpinstallPromptMessage.neverAllow=No permitir nunca +xpinstallPromptMessage.neverAllow.accesskey=o +# Accessibility Note: +# Be sure you do not choose an accesskey that is used elsewhere in the active context (e.g. main menu bar, submenu of the warning popup button) +# See https://website-archive.mozilla.org/www.mozilla.org/access/access/keyboard/ for details +xpinstallPromptMessage.install=Continuar con la instalación +xpinstallPromptMessage.install.accesskey=C + +# Accessibility Note: +# Be sure you do not choose an accesskey that is used elsewhere in the active context (e.g. main menu bar, submenu of the warning popup button) +# See http://www.mozilla.org/access/keyboard/accesskey for details +xpinstallDisabledMessageLocked=La instalación de software ha sido desactivada por su administrador de sistema. +xpinstallDisabledMessage=La instalación de software está actualmente desactivada. Pulse Activar y vuelva a intentarlo. +xpinstallDisabledButton=Activar +xpinstallDisabledButton.accesskey=A + +# LOCALIZATION NOTE (addonInstallBlockedByPolicy) +# This message is shown when the installation of an add-on is blocked by +# enterprise policy. %1$S is replaced by the name of the add-on. +# %2$S is replaced by the ID of add-on. %3$S is a custom message that +# the administration can add to the message. +addonInstallBlockedByPolicy=%1$S (%2$S) está bloqueado por su administrador del sistema. %3$S + +# LOCALIZATION NOTE (addonPostInstall.message2) +# %S is replaced with the localized named of the extension that was +# just installed. +addonPostInstall.message2=Se ha añadido %S + +# LOCALIZATION NOTE (addonDownloadingAndVerifying): +# Semicolon-separated list of plural forms. See: +# http://developer.mozilla.org/en/docs/Localization_and_Plurals +# Also see https://bugzilla.mozilla.org/show_bug.cgi?id=570012 for mockups +addonDownloadingAndVerifying=Descargando y verificando complemento…;Descargando y verificando #1 complementos… +addonDownloadVerifying=Verificando + +addonInstall.unsigned=(No verificado) +addonInstall.cancelButton.label=Cancelar +addonInstall.cancelButton.accesskey=C +addonInstall.acceptButton2.label=Añadir +addonInstall.acceptButton2.accesskey=A + +# LOCALIZATION NOTE (addonConfirmInstallMessage,addonConfirmInstallUnsigned): +# Semicolon-separated list of plural forms. See: +# http://developer.mozilla.org/en/docs/Localization_and_Plurals +# #1 is brandShortName +# #2 is the number of add-ons being installed +addonConfirmInstall.message=Este sitio quiere instalar un complemento en #1:;Este sitio quiere instalar #2 complementos en #1: +addonConfirmInstallUnsigned.message=Precaución: este complemento desea instalar un complemento no verificado en #1. Continúe bajo su responsabilidad.;Precaución: este complemento desea instalar #2 complementos no verificados en #1. Continúe bajo su responsabilidad. + +# LOCALIZATION NOTE (addonConfirmInstallSomeUnsigned.message): +# Semicolon-separated list of plural forms. See: +# http://developer.mozilla.org/en/docs/Localization_and_Plurals +# #1 is brandShortName +# #2 is the total number of add-ons being installed (at least 2) +addonConfirmInstallSomeUnsigned.message=;Precaución: este sitio desea instalar #2 complementos en #1, algunos de los cuales no están verificados. Continúe bajo su responsabilidad. + +# LOCALIZATION NOTE (addonInstalled): +# %S is the name of the add-on +addonInstalled=%S ha sido instalado con éxito. +# LOCALIZATION NOTE (addonsGenericInstalled): +# Semicolon-separated list of plural forms. See: +# http://developer.mozilla.org/en/docs/Localization_and_Plurals +# #1 number of add-ons +addonsGenericInstalled=#1 complemento ha sido instalado con éxito.;#1 complementos han sido instalados con éxito. + +# LOCALIZATION NOTE (addonInstallError-1, addonInstallError-2, addonInstallError-3, addonInstallError-4, addonInstallError-5, addonLocalInstallError-1, addonLocalInstallError-2, addonLocalInstallError-3, addonLocalInstallError-4, addonLocalInstallError-5): +# %1$S is the application name, %2$S is the add-on name +addonInstallError-1=El complemento no ha podido descargarse por un fallo de conexión. +addonInstallError-2=Este complemento no se ha podido instalar porque no coincide con el complemento %1$S esperado. +addonInstallError-3=El complemento descargado desde este sitio no ha podido instalarse porque parece estar dañado. +addonInstallError-4=%2$S no ha podido ser instalado porque %1$S no puede modificar el archivo requerido. +addonInstallError-5=%1$S ha evitado que este sitio instale un complemento no verificado. +addonLocalInstallError-1=Este complemento no se ha podido instalar por un fallo del sistema de archivos. +addonLocalInstallError-2=Este complemento no se ha podido instalar porque no coincide con el complemento %1$S esperado. +addonLocalInstallError-3=Este complemento no se ha podido instalar porque parece estar dañado. +addonLocalInstallError-4=%2$S no ha podido ser instalado porque %1$S no puede modificar el archivo requerido. +addonLocalInstallError-5=Este complemento ha podido ser instalado porque no ha sido verificado. + +# LOCALIZATION NOTE (addonInstallErrorIncompatible): +# %1$S is the application name, %2$S is the application version, %3$S is the add-on name +addonInstallErrorIncompatible=%3$S no ha podido ser instalado porque no es compatible con %1$S %2$S. + +# LOCALIZATION NOTE (addonInstallErrorBlocklisted): %S is add-on name +addonInstallErrorBlocklisted=%S no ha podido ser instalado porque tiene un alto riesgo de causar problemas de estabilidad o seguridad. + +# LOCALIZATION NOTE (webextPerms.header,webextPerms.headerWithPerms,webextPerms.headerUnsigned,webextPerms.headerUnsignedWithPerms) +# These strings are used as headers in the webextension permissions dialog, +# %S is replaced with the localized name of the extension being installed. +# See https://bug1308309.bmoattachments.org/attachment.cgi?id=8814612 +# for an example of the full dialog. +# Note, these strings will be used as raw markup. Avoid characters like <, >, & +webextPerms.header=¿Añadir %S? + +# %S is brandShortName +webextPerms.experimentWarning=Los complementos maliciosos pueden robar su información privada o comprometer su equipo. Instale este complemento únicamente si confía en el origen. +webextPerms.headerWithPerms=¿Añadir %S? Esta extensión tendrá permiso para: +webextPerms.headerUnsigned=¿Añadir %S? Esta extensión no está verificada. Las extensiones maliciosas pueden robar su información privada o poner en peligro su ordenador. Instálela solamente si confía en la fuente. +webextPerms.headerUnsignedWithPerms=¿Añadir %S? Esta extensión no está verificada. Extensiones maliciosas puede robar su información privada o comprometer su ordenador. Añádala solo si confía en la fuente. Esta extensión tendrá permiso para: +webextPerms.learnMore2=Más información +webextPerms.add.label=Añadir +webextPerms.add.accessKey=A +webextPerms.cancel.label=Cancelar +webextPerms.cancel.accessKey=C + +# LOCALIZATION NOTE (webextPerms.sideloadMenuItem) +# %1$S will be replaced with the localized name of the sideloaded add-on. +# %2$S will be replace with the name of the application (e.g., Firefox, Nightly) +webextPerms.sideloadMenuItem=%1$S añadido a %2$S + +# LOCALIZATION NOTE (webextPerms.sideloadHeader) +# This string is used as a header in the webextension permissions dialog +# when the extension is side-loaded. +# %S is replaced with the localized name of the extension being installed. +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextPerms.sideloadHeader=%S añadido +webextPerms.sideloadText2=Otro programa en su equipo ha instalado un complemento que puede afectar a su navegador. Revise los permisos que solicita este complemento y elija Activar o Cancelar (para dejarlo desactivado). +webextPerms.sideloadTextNoPerms=Otro programa en su equipo ha instalado un complemento que puede afectar a su navegador. Elija Activar o Cancelar (para dejarlo desactivado). + +webextPerms.sideloadEnable.label=Activar +webextPerms.sideloadEnable.accessKey=v +webextPerms.sideloadCancel.label=Cancelar +webextPerms.sideloadCancel.accessKey=C + +# LOCALIZATION NOTE (webextPerms.updateMenuItem) +# %S will be replaced with the localized name of the extension which +# has been updated. +webextPerms.updateMenuItem=%S requiere nuevos permisos + +# LOCALIZATION NOTE (webextPerms.updateText2) +# %S is replaced with the localized name of the updated extension. +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextPerms.updateText2=Se ha actualizado %S. Tiene que aprobar nuevos permisos antes de poder instalar la nueva versión. Si selecciona “Cancelar”, seguirá con la versión actual de la extensión. Esta extensión tendrá permiso para: + +webextPerms.updateAccept.label=Actualizar +webextPerms.updateAccept.accessKey=U + +# LOCALIZATION NOTE (webextPerms.optionalPermsHeader) +# %S is replace with the localized name of the extension requested new +# permissions. +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextPerms.optionalPermsHeader=%S solicita permisos adicionales. +webextPerms.optionalPermsListIntro=Quiere: +webextPerms.optionalPermsAllow.label=Permitir +webextPerms.optionalPermsAllow.accessKey=P +webextPerms.optionalPermsDeny.label=Denegar +webextPerms.optionalPermsDeny.accessKey=D + +webextPerms.description.accountsFolders=Crear, renombrar o eliminar sus carpetas de cuentas de correo +webextPerms.description.accountsIdentities=Crear, modificar o eliminar sus identidades de cuentas de correo +webextPerms.description.accountsRead2=Ver sus cuentas de correo, sus identidades y sus carpetas +webextPerms.description.addressBooks=Leer y modificar sus libretas de direcciones y contactos +webextPerms.description.bookmarks=Leer y modificar marcadores +webextPerms.description.browserSettings=Leer y modificar la configuración del navegador +webextPerms.description.browsingData=Limpiar el historial de navegación reciente, las cookies y datos relacionados +webextPerms.description.clipboardRead=Obtener datos del portapapeles +webextPerms.description.clipboardWrite=Enviar datos al portapapeles +webextPerms.description.compose=Leer y modificar sus mensajes de correo mientras los redacta y envía +webextPerms.description.compose.send=Enviar mensajes de correo electrónico redactados en su nombre +webextPerms.description.devtools=Extender las herramientas de desarrollador para acceder a sus datos en las pestañas abiertas +webextPerms.description.dns=Acceder a la información de la dirección IP y el nombre de equipo +webextPerms.description.downloads=Descargar archivos y leer y modificar el historial de descargas del navegador +webextPerms.description.downloads.open=Abrir archivos descargados en su equipo +# LOCALIZATION NOTE (webextPerms.description.experiment) +# %S will be replaced with the name of the application +webextPerms.description.experiment=Tener acceso completo y sin restricciones a %S y a su equipo. +webextPerms.description.find=Leer el texto de todas las pestañas abiertas +webextPerms.description.geolocation=Acceder a su ubicación +webextPerms.description.history=Acceder al historial de navegación +webextPerms.description.management=Monitorizar el uso de extensiones y administrar temas +webextPerms.description.messagesModify=Leer y modificar los mensajes de correo que se le muestran +webextPerms.description.messagesMove2=Copiar o mover sus mensajes de correo (incluyendo moverlos a la carpeta de la papelera) +webextPerms.description.messagesDelete=Eliminar permanentemente sus mensajes de correo electrónico +webextPerms.description.messagesRead=Lea sus mensajes de correo y márquelos o etiquételos +# LOCALIZATION NOTE (webextPerms.description.nativeMessaging) +# %S will be replaced with the name of the application +webextPerms.description.nativeMessaging=Intercambiar mensajes con otros programas distintos de %S +webextPerms.description.notifications=Mostrarle notificaciones +webextPerms.description.pkcs11=Proporcionar servicios de autenticación criptográfica +webextPerms.description.privacy=Leer y modificar la configuración de privacidad +webextPerms.description.proxy=Controlar la configuración del proxy del navegador +webextPerms.description.sessions=Acceder a las pestañas cerradas recientemente +webextPerms.description.tabs=Acceder a las pestañas del navegador +webextPerms.description.tabHide=Ocultar y mostrar las pestañas del navegador +webextPerms.description.topSites=Acceder al historial de navegación +webextPerms.description.unlimitedStorage=Guardar una cantidad ilimitada de datos en el lado del cliente +webextPerms.description.webNavigation=Acceder a la actividad del navegador durante la navegación + +webextPerms.hostDescription.allUrls=Acceder a sus datos de todos los sitios web + +# LOCALIZATION NOTE (webextPerms.hostDescription.wildcard) +# %S will be replaced by the DNS domain for which a webextension +# is requesting access (e.g., mozilla.org) +webextPerms.hostDescription.wildcard=Acceder a sus datos de sitios en el dominio %S + +# LOCALIZATION NOTE (webextPerms.hostDescription.tooManyWildcards): +# Semi-colon list of plural forms. +# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals +# #1 will be replaced by an integer indicating the number of additional +# domains for which this webextension is requesting permission. +webextPerms.hostDescription.tooManyWildcards=Acceder a sus datos en #1 dominio más;Acceder a sus datos en #1 dominios más + +# LOCALIZATION NOTE (webextPerms.hostDescription.oneSite) +# %S will be replaced by the DNS host name for which a webextension +# is requesting access (e.g., www.mozilla.org) +webextPerms.hostDescription.oneSite=Acceder a sus datos de %S + +# LOCALIZATION NOTE (webextPerms.hostDescription.tooManySites) +# Semi-colon list of plural forms. +# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals +# #1 will be replaced by an integer indicating the number of additional +# hosts for which this webextension is requesting permission. +webextPerms.hostDescription.tooManySites=Acceder a sus datos en #1 sitio más;Acceder a sus datos en #1 sitios más + +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextSitePerms.headerWithPerms=¿Añadir %1$S? Esta extensión concede los siguientes permisos a %2$S: +webextSitePerms.headerUnsignedWithPerms=¿Añadir %1$S? Esta extensión no está verificada. Las extensiones maliciosas pueden robar su información privada o comprometer su ordenador. Añádala únicamente si confía en la fuente. Esta extensión concede los siguientes permisos a %2$S: + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties +webextSitePerms.description.midi=Acceder a dispositivos MIDI +webextSitePerms.description.midi-sysex=Acceder a dispositivos MIDI con soporte para SysEx + +# LOCALIZATION NOTE (webext.defaultSearch.description) +# %1$S is replaced with the localized named of the extension that is asking to change the default search engine. +# %2$S is replaced with the name of the current search engine +# %3$S is replaced with the name of the new search engine +webext.defaultSearch.description=%1$S quiere cambiar su buscador predeterminado de %2$S a %3$S. ¿Es correcto? +webext.defaultSearchYes.label=Sí +webext.defaultSearchYes.accessKey=S +webext.defaultSearchNo.label=No +webext.defaultSearchNo.accessKey=N diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/addressbook/abMainWindow.dtd thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/addressbook/abMainWindow.dtd --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/addressbook/abMainWindow.dtd 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/addressbook/abMainWindow.dtd 2022-04-15 07:52:23.000000000 +0000 @@ -2,193 +2,216 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/addressbook/addressBook.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/addressbook/addressBook.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/addressbook/addressBook.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/addressbook/addressBook.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,128 +2,177 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -mailingListTitleEdit = Editar %S -emptyListName = Debe introducir un nombre de lista. -badListNameCharacters = Un nombre de lista no puede contener ninguno de los siguientes caracteres: < > ; , " -badListNameSpaces = Un nombre de lista no puede contener múltiples espacios adyacentes. -lastFirstFormat = %S, %S -firstLastFormat = %S %S - -allAddressBooks = Todas las libretas de direcciones - -newContactTitle = Nuevo contacto -newContactTitleWithDisplayName = Nuevo contacto de %S -editContactTitle = Editar contacto -editContactTitleWithDisplayName = Editar contacto de %S -editVCardTitle = Editar vCard -editVCardTitleWithDisplayName = Editar vCard de %S - -cardRequiredDataMissingMessage = Debe introducir al menos uno de los siguientes elementos:\nDirección de correo, Nombre, Apellido, Nombre mostrado, Organización. -cardRequiredDataMissingTitle = Falta información requerida -incorrectEmailAddressFormatMessage = La dirección primaria de correo electrónico debe ser de la forma usuario@maquina. -incorrectEmailAddressFormatTitle = Formato incorrecto de la dirección de correo electrónico - -viewListTitle = Lista de correo: %S -mailListNameExistsTitle = Ya existe la lista de correo. -mailListNameExistsMessage = Ya existe una lista de correo con ese nombre. Escoja un nombre diferente. - -propertyPrimaryEmail = Correo electrónico -propertyListName = Nombre de la lista -propertySecondaryEmail = Correo electrónico adicional -propertyNickname = Apodo -propertyDisplayName = Nombre mostrado -propertyWork = Trabajo -propertyHome = Casa -propertyFax = Fax -propertyCellular = Móvil -propertyPager = Buscapersonas -propertyBirthday = Cumpleaños -propertyCustom1 = Personalizado 1 -propertyCustom2 = Personalizado 2 -propertyCustom3 = Personalizado 3 -propertyCustom4 = Personalizado 4 - -propertyGtalk = Google Talk -propertyAIM = AIM -propertyYahoo = Yahoo! -propertySkype = Skype -propertyQQ = QQ -propertyMSN = MSN -propertyICQ = ICQ -propertyXMPP = ID de Jabber -propertyIRC = Apodo en IRC - -cityAndStateAndZip = %1$S, %2$S %3$S -cityAndStateNoZip = %1$S, %2$S -cityOrStateAndZip = %1$S %2$S - -stateZipSeparator = - -prefixTo = A -prefixCc = Cc -prefixBcc = Bcc -addressBook = Libreta de direcciones - -browsePhoto = Foto de contacto -stateImageSave = Guardando la imagen… -errorInvalidUri = Error: origen de la imagen no válido. -errorNotAvailable = Error: el archivo no es accesible. -errorInvalidImage = Error: solo se admiten los tipos de imagen JPG, PNG y GIF. -errorSaveOperation = Error: no se ha podido guardar la imagen. - -ldap_2.servers.pab.description = Libreta de direcciones personal -ldap_2.servers.history.description = Direcciones recopiladas -ldap_2.servers.osx.description = Libreta de direcciones de Mac OS X - -totalContactStatus = Total de contactos en %1$S: %2$S -noMatchFound = No se han encontrado coincidencias -matchesFound1 = #1 coincidencia encontrada;#1 coincidencias encontradas - -contactsCopied = %1$S contacto copiado;%1$S contactos copiados - -contactsMoved = %1$S contacto movido;%1$S contactos movidos - -invalidName = Introduzca un nombre válido. -invalidHostname = Introduzca un nombre de servidor válido. -invalidPortNumber = Introduzca un número de puerto válido. -invalidResults = Introduzca un número válido en el campo de resultados. -abReplicationOfflineWarning = Debe estar conectado para realizar una replicación LDAP. -abReplicationSaveSettings = Debe guardarse la configuración antes de que se pueda descargar un directorio. - -ExportAddressBookNameTitle = Exportar libreta de direcciones - %S -LDIFFiles = LDIF -CSVFiles = Separado por comas -CSVFilesSysCharset = Separado por comas (codificación de caracteres del sistema) -CSVFilesUTF8 = Separado por comas (UTF-8) -TABFiles = Delimitado por tabuladores -TABFilesSysCharset = Delimitado por tabuladores (codificación de caracteres del sistema) -TABFilesUTF8 = Delimitado por tabuladores (UTF-8) -VCFFiles = vCard -SupportedABFiles = Archivos de libreta de direcciones admitidos -failedToExportTitle = Fallo al exportar -failedToExportMessageNoDeviceSpace = Fallo al exportar la libreta de direcciones. No queda espacio en el dispositivo. -failedToExportMessageFileAccessDenied = Fallo al exportar la libreta de direcciones. Acceso al archivo denegado. - -AuthDlgTitle = Réplica LDAP de libreta de direcciones -AuthDlgDesc = Para acceder al servidor de directorio, introduzca su usuario y contraseña. - -joinMeInThisChat = Únete+a+mí+en+este+chat. - -headingHome = Casa -headingWork = Trabajo -headingOther = Otro -headingChat = Charlar -headingPhone = Teléfono -headingDescription = Descripción -headingAddresses = Direcciones - -addressBookTitleNew = Nueva libreta de direcciones -addressBookTitleEdit = Propiedades de %S -duplicateNameTitle = Nombre de libreta duplicado -duplicateNameText = Ya existe una libreta de direcciones con este nombre:\n• %S - -corruptMabFileTitle = Archivo de libreta de direcciones corrupto -corruptMabFileAlert = Una de sus libretas de direcciones (archivo %1$S) no pudo leerse. Se crearán un nuevo archivo %2$S y una copia del archivo antiguo, llamada %3$S, en el mismo directorio. - -lockedMabFileTitle = No se pudo cargar el fichero de la libreta de direcciones -lockedMabFileAlert = No se pudo cargar el fichero de la libreta de direcciones %S. Puede que sea de sólo lectura, o esté bloqueado por otra aplicación. Vuelva a intentarlo más tarde. +# The following are used by the Mailing list dialog. +# LOCALIZATION NOTE (mailingListTitleEdit): %S will be replaced by the Mailing List's display name. +mailingListTitleEdit=Editar %S +emptyListName=Debe introducir un nombre de lista. +badListNameCharacters=Un nombre de lista no puede contener ninguno de los siguientes caracteres: < > ; , " +badListNameSpaces=Un nombre de lista no puede contener múltiples espacios adyacentes. +lastFirstFormat=%S, %S +firstLastFormat=%S %S + +allAddressBooks=Todas las libretas de direcciones + +newContactTitle=Nuevo contacto +# %S will be the contact's display name +newContactTitleWithDisplayName=Nuevo contacto de %S +editContactTitle=Editar contacto +# %S will be the contact's display name +editContactTitleWithDisplayName=Editar contacto de %S +# don't translate vCard +editVCardTitle=Editar vCard +# %S will be the card's display name, don't translate vCard +editVCardTitleWithDisplayName=Editar vCard de %S + +## LOCALIZATION NOTE (cardRequiredDataMissingMessage): do not localize \n +cardRequiredDataMissingMessage=Debe introducir al menos uno de los siguientes elementos:\nDirección de correo, Nombre, Apellido, Nombre mostrado, Organización. +cardRequiredDataMissingTitle=Falta información requerida +incorrectEmailAddressFormatMessage=La dirección primaria de correo electrónico debe ser de la forma usuario@maquina. +incorrectEmailAddressFormatTitle=Formato incorrecto de la dirección de correo electrónico + +viewListTitle=Lista de correo: %S +mailListNameExistsTitle=Ya existe la lista de correo. +mailListNameExistsMessage=Ya existe una lista de correo con ese nombre. Escoja un nombre diferente. + +propertyPrimaryEmail=Correo electrónico +propertyListName=Nombre de la lista +propertySecondaryEmail=Correo electrónico adicional +propertyNickname=Apodo +propertyDisplayName=Nombre mostrado +propertyWork=Trabajo +propertyHome=Casa +propertyFax=Fax +propertyCellular=Móvil +propertyPager=Buscapersonas +propertyBirthday=Cumpleaños +propertyCustom1=Personalizado 1 +propertyCustom2=Personalizado 2 +propertyCustom3=Personalizado 3 +propertyCustom4=Personalizado 4 + +propertyGtalk=Google Talk +propertyAIM=AIM +propertyYahoo=Yahoo! +propertySkype=Skype +propertyQQ=QQ +propertyMSN=MSN +propertyICQ=ICQ +propertyXMPP=ID de Jabber +propertyIRC=Apodo en IRC + +## LOCALIZATION NOTE (cityAndStateAndZip): +## %1$S is city, %2$S is state, %3$S is zip +cityAndStateAndZip=%1$S, %2$S %3$S +## LOCALIZATION NOTE (cityAndStateNoZip): +## %1$S is city, %2$S is state +cityAndStateNoZip=%1$S, %2$S +## LOCALIZATION NOTE (cityOrStateAndZip): +## %1$S is city or state, %2$S is zip +cityOrStateAndZip=%1$S %2$S + +stateZipSeparator= + +prefixTo=A +prefixCc=Cc +prefixBcc=Bcc +addressBook=Libreta de direcciones + +# Contact photo management +browsePhoto=Foto de contacto +stateImageSave=Guardando la imagen… +errorInvalidUri=Error: origen de la imagen no válido. +errorNotAvailable=Error: el archivo no es accesible. +errorInvalidImage=Error: solo se admiten los tipos de imagen JPG, PNG y GIF. +errorSaveOperation=Error: no se ha podido guardar la imagen. + +# mailnews.js +ldap_2.servers.pab.description=Libreta de direcciones personal +ldap_2.servers.history.description=Direcciones recopiladas +## LOCALIZATION NOTE (ldap_2.servers.osx.description is only used on Mac OS X) +ldap_2.servers.osx.description=Libreta de direcciones de Mac OS X +## LOCALIZATION NOTE (ldap_2.servers.outlook.description is only used on Windows) +ldap_2.servers.outlook.description=Libreta de direcciones de Outlook + +# status bar stuff +## LOCALIZATION NOTE (totalContactStatus): +## %1$S is address book name, %2$S is contact count +totalContactStatus=Total de contactos en %1$S: %2$S +noMatchFound=No se han encontrado coincidencias +## LOCALIZATION NOTE (matchesFound1): +## Semicolon-separated list of singular and plural forms. +## See: https://developer.mozilla.org/docs/Mozilla/Localization/Localization_and_Plurals +## #1 is the number of matching contacts found +matchesFound1=#1 coincidencia encontrada;#1 coincidencias encontradas + +## LOCALIZATION NOTE (contactsCopied): Semi-colon list of plural forms +## %1$S is the number of contacts that were copied. This should be used multiple +## times wherever you need it. Do not replace by %S. +contactsCopied=%1$S contacto copiado;%1$S contactos copiados + +## LOCALIZATION NOTE (contactsMoved): Semi-colon list of plural forms +## %1$S is the number of contacts that were moved. This should be used multiple +## times wherever you need it. Do not replace by %S. +contactsMoved=%1$S contacto movido;%1$S contactos movidos + +# LDAP directory stuff +invalidName=Introduzca un nombre válido. +invalidHostname=Introduzca un nombre de servidor válido. +invalidPortNumber=Introduzca un número de puerto válido. +invalidResults=Introduzca un número válido en el campo de resultados. +abReplicationOfflineWarning=Debe estar conectado para realizar una replicación LDAP. +abReplicationSaveSettings=Debe guardarse la configuración antes de que se pueda descargar un directorio. + +# For importing / exporting +## LOCALIZATION NOTE (ExportAddressBookNameTitle): %S is the name of exported addressbook +ExportAddressBookNameTitle=Exportar libreta de direcciones - %S +LDIFFiles=LDIF +CSVFiles=Separado por comas +CSVFilesSysCharset=Separado por comas (codificación de caracteres del sistema) +CSVFilesUTF8=Separado por comas (UTF-8) +TABFiles=Delimitado por tabuladores +TABFilesSysCharset=Delimitado por tabuladores (codificación de caracteres del sistema) +TABFilesUTF8=Delimitado por tabuladores (UTF-8) +VCFFiles=vCard +SupportedABFiles=Archivos de libreta de direcciones admitidos +failedToExportTitle=Fallo al exportar +failedToExportMessageNoDeviceSpace=Fallo al exportar la libreta de direcciones. No queda espacio en el dispositivo. +failedToExportMessageFileAccessDenied=Fallo al exportar la libreta de direcciones. Acceso al archivo denegado. + +# For getting authDN for replication using dlg box +AuthDlgTitle=Réplica LDAP de libreta de direcciones +AuthDlgDesc=Para acceder al servidor de directorio, introduzca su usuario y contraseña. + +# LOCALIZATION NOTE(joinMeInThisChat) +# use + for spaces +joinMeInThisChat=Únete+a+mí+en+este+chat. + +# For printing +headingHome=Casa +headingWork=Trabajo +headingOther=Otro +headingChat=Charlar +headingPhone=Teléfono +headingDescription=Descripción +headingAddresses=Direcciones + +## For address books +addressBookTitleNew=Nueva libreta de direcciones +# LOCALIZATION NOTE (addressBookTitleEdit): +# %S is the current name of the address book. +# Example: My Custom AB Properties +addressBookTitleEdit=Propiedades de %S +duplicateNameTitle=Nombre de libreta duplicado +# LOCALIZATION NOTE (duplicateNameText): +# Don't localize "\n• %S" unless your local layout comes out wrong. +# %S is the name of the existing address book. +# Example: An address book with this name already exists: +# • My Custom AB +duplicateNameText=Ya existe una libreta de direcciones con este nombre:\n• %S + +# For corrupt .mab files +corruptMabFileTitle=Archivo de libreta de direcciones corrupto +corruptMabFileAlert=Una de sus libretas de direcciones (archivo %1$S) no pudo leerse. Se crearán un nuevo archivo %2$S y una copia del archivo antiguo, llamada %3$S, en el mismo directorio. + +# For locked .mab files +lockedMabFileTitle=No se pudo cargar el fichero de la libreta de direcciones +lockedMabFileAlert=No se pudo cargar el fichero de la libreta de direcciones %S. Puede que sea de sólo lectura, o esté bloqueado por otra aplicación. Vuelva a intentarlo más tarde. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/chat.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/chat.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/chat.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/chat.properties 2022-04-15 07:52:23.000000000 +0000 @@ -29,7 +29,9 @@ # sends a verification request for end-to-end encryption keys. # %S is replaced with the display name of the user or, if this is to verify a # session of yourself, a string that identifies the session. +buddy.verificationRequest.label=%S quiere verificar las identidades de los demás buddy.verificationRequest.allow.label=Iniciar verificación +buddy.verificationRequest.allow.accesskey=I buddy.verificationRequest.deny.label=Denegar buddy.verificationRequest.deny.accesskey=D diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/gloda.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/gloda.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/gloda.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/gloda.properties 2022-04-15 07:52:23.000000000 +0000 @@ -57,52 +57,119 @@ # #1, if present, is replaced by the value of the facet (name, folder, mailing # list, etc.) -gloda.message.attr.account.facetNameLabel = Cuenta -gloda.message.attr.account.mustMatchLabel = debe estar en #1 -gloda.message.attr.account.cantMatchLabel = no puede estar en #1 - -gloda.message.attr.folder.facetNameLabel = Carpeta -gloda.message.attr.folder.mustMatchLabel = debe estar en #1 -gloda.message.attr.folder.cantMatchLabel = no puede estar en #1 - -gloda.message.attr.fromMe.facetNameLabel = De mí - -gloda.message.attr.toMe.facetNameLabel = A mí - -gloda.message.attr.involves.facetNameLabel = Gente -gloda.message.attr.involves.includeLabel = involucrando a cualquiera de: -gloda.message.attr.involves.excludeLabel = no involucrando: -gloda.message.attr.involves.remainderLabel = otros participantes: -gloda.message.attr.involves.mustMatchLabel = debe involucrar a #1 -gloda.message.attr.involves.cantMatchLabel = no puede involucrar a #1 - -gloda.message.attr.date.facetNameLabel = Fecha - -gloda.message.attr.attachmentTypes.facetNameLabel = Adjuntos - -gloda.message.attr.mailing-list.facetNameLabel = Lista de correo -gloda.message.attr.mailing-list.mustMatchLabel = debe estar en #1 -gloda.message.attr.mailing-list.cantMatchLabel = no puede estar en #1 -gloda.message.attr.mailing-list.mustMatchSomeLabel = debe estar en una lista de correo -gloda.message.attr.mailing-list.mustMatchNoneLabel = no puede estar en una lista de correo - -gloda.message.attr.tag.facetNameLabel = Etiquetas -gloda.message.attr.tag.mustMatchLabel = debe estar etiquetado con #1 -gloda.message.attr.tag.cantMatchLabel = no puede estar etiquetado con #1 -gloda.message.attr.tag.mustMatchSomeLabel = debe estar etiquetado -gloda.message.attr.tag.mustMatchNoneLabel = no puede estar etiquetado - -gloda.message.attr.star.facetNameLabel = Con estrella - -gloda.message.attr.read.facetNameLabel = Leído - -gloda.message.attr.repliedTo.facetNameLabel = Respondido a - -gloda.message.attr.forwarded.facetNameLabel = Re-enviado - -gloda.mimetype.category.archives.label = Archivos -gloda.mimetype.category.documents.label = Documentos -gloda.mimetype.category.images.label = Imágenes -gloda.mimetype.category.media.label = Medios (audio, vídeo) -gloda.mimetype.category.pdf.label = Archivos PDF -gloda.mimetype.category.other.label = Otros +# LOCALIZATION NOTE (gloda.message.attr.account.*): Stores the account in which +# a message's folder is located. +gloda.message.attr.account.facetNameLabel=Cuenta +gloda.message.attr.account.includeLabel=almacenada en cualquiera de: +gloda.message.attr.account.excludeLabel=no almacenada en: +gloda.message.attr.account.remainderLabel=otras cuentas: +gloda.message.attr.account.mustMatchLabel=debe estar en #1 +gloda.message.attr.account.cantMatchLabel=no puede estar en #1 + +# LOCALIZATION NOTE (gloda.message.attr.folder.*): Stores the message folder in +# which the message is stored. +gloda.message.attr.folder.facetNameLabel=Carpeta +gloda.message.attr.folder.includeLabel=almacenada en cualquiera de: +gloda.message.attr.folder.excludeLabel=no almacenada en: +gloda.message.attr.folder.remainderLabel=otras carpetas: +gloda.message.attr.folder.mustMatchLabel=debe estar en #1 +gloda.message.attr.folder.cantMatchLabel=no puede estar en #1 + +# LOCALIZATION NOTE (gloda.message.attr.fromMe.*): Stores everyone involved +# with the message. This means from/to/cc/bcc. +gloda.message.attr.fromMe.facetNameLabel=De mí + +# LOCALIZATION NOTE (gloda.message.attr.toMe.*): Stores everyone involved +# with the message. This means from/to/cc/bcc. +gloda.message.attr.toMe.facetNameLabel=A mí + +# LOCALIZATION NOTE (gloda.message.attr.involves.*): Stores everyone involved +# with the message. This means from/to/cc/bcc. +gloda.message.attr.involves.facetNameLabel=Gente +gloda.message.attr.involves.includeLabel=involucrando a cualquiera de: +gloda.message.attr.involves.excludeLabel=no involucrando: +gloda.message.attr.involves.remainderLabel=otros participantes: +gloda.message.attr.involves.mustMatchLabel=debe involucrar a #1 +gloda.message.attr.involves.cantMatchLabel=no puede involucrar a #1 + +# LOCALIZATION NOTE (gloda.message.attr.date.*): Stores the date of the message. +# Thunderbird normally stores the date the message claims it was composed +# according to the "Date" header. This is not the same as when the message +# was sent or when it was eventually received by the user. In the future we +# may change this to be one of the other dates, but not anytime soon. +gloda.message.attr.date.facetNameLabel=Fecha + +# LOCALIZATION NOTE (gloda.message.attr.attachmentTypes.*): Stores the list of +# MIME types (ex: image/png, text/plain) of real attachments (not just part of +# the message content but explicitly named attachments) on the message. +# Although we hope to be able to provide localized human-readable explanations +# of the MIME type (ex: "PowerPoint document"), I don't know if that is going +# to happen. +gloda.message.attr.attachmentTypes.facetNameLabel=Adjuntos + +# LOCALIZATION NOTE (gloda.message.attr.mailing-list.*): Stores the mailing +# lists detected in the message. This will normally be the e-mail address of +# the mailing list and only be detected in messages received from the mailing +# list. Extensions may contribute additional detected mailing-list-like +# things. +gloda.message.attr.mailing-list.facetNameLabel=Lista de correo +gloda.message.attr.mailing-list.noneLabel=Ninguno +gloda.message.attr.mailing-list.includeLabel=recibido en cualquiera de: +gloda.message.attr.mailing-list.excludeLabel=no recibido en ninguna de: +gloda.message.attr.mailing-list.remainderLabel=otras listas de correo: +gloda.message.attr.mailing-list.mustMatchLabel=debe estar en #1 +gloda.message.attr.mailing-list.cantMatchLabel=no puede estar en #1 +gloda.message.attr.mailing-list.mustMatchSomeLabel=debe estar en una lista de correo +gloda.message.attr.mailing-list.mustMatchNoneLabel=no puede estar en una lista de correo + +# LOCALIZATION NOTE (gloda.message.attr.tag.*): Stores the tags applied to the +# message. Notably, gmail's labels are not currently exposed via IMAP and we +# do not do anything clever with gmail, so this is independent of gmail labels +# This may change in the future, but it's a safe bet it's not happening on +# Thunderbird's side prior to 3.0. +gloda.message.attr.tag.facetNameLabel=Etiquetas +gloda.message.attr.tag.noneLabel=Ninguna +gloda.message.attr.tag.includeLabel=etiquetado cualquiera de: +gloda.message.attr.tag.excludeLabel=sin etiquetar: +gloda.message.attr.tag.remainderLabel=otras etiquetas: +gloda.message.attr.tag.mustMatchLabel=debe estar etiquetado con #1 +gloda.message.attr.tag.cantMatchLabel=no puede estar etiquetado con #1 +gloda.message.attr.tag.mustMatchSomeLabel=debe estar etiquetado +gloda.message.attr.tag.mustMatchNoneLabel=no puede estar etiquetado + +# LOCALIZATION NOTE (gloda.message.attr.star.*): Stores whether the message is +# starred or not, as indicated by a pretty star icon. In the past, the icon +# used to be a flag. The IMAP terminology continues to be "flagged". +gloda.message.attr.star.facetNameLabel=Con estrella + +# LOCALIZATION NOTE (gloda.message.attr.read.*): Stores whether the user has +# read the message or not. +gloda.message.attr.read.facetNameLabel=Leído + +# LOCALIZATION NOTE (gloda.message.attr.repliedTo.*): Stores whether we believe +# the user has ever replied to the message. We normally show a little icon in +# the thread pane when this is the case. +gloda.message.attr.repliedTo.facetNameLabel=Respondido a + +# LOCALIZATION NOTE (gloda.message.attr.forwarded.*): Stores whether we believe +# the user has ever forwarded the message. We normally show a little icon in +# the thread pane when this is the case. +gloda.message.attr.forwarded.facetNameLabel=Re-enviado + +# LOCALIZATION NOTE (gloda.mimetype.category.*.label): Map categories of MIME +# types defined in MimeTypeCategories to labels. +# LOCALIZATION NOTE (gloda.mimetype.category.archives.label): Archive is +# referring to things like zip files, tar files, tar.gz files, etc. +gloda.mimetype.category.archives.label=Archivos +gloda.mimetype.category.documents.label=Documentos +gloda.mimetype.category.images.label=Imágenes +# LOCALIZATION NOTE (gloda.mimetype.category.media.label): Media is meant to +# encompass both audio and video. This is because video and audio streams are +# frequently stored in the same type of container and we cannot rely on the +# sending e-mail client to have been clever enough to figure out what was +# really in the file. So we group them together. +gloda.mimetype.category.media.label=Medios (audio, vídeo) +gloda.mimetype.category.pdf.label=Archivos PDF +# LOCALIZATION NOTE (gloda.mimetype.category.other.label): Other is the category +# for MIME types that we don't really know what it is. +gloda.mimetype.category.other.label=Otros diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/imapMsgs.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/imapMsgs.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/imapMsgs.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/imapMsgs.properties 2022-04-15 07:52:23.000000000 +0000 @@ -6,165 +6,263 @@ # The following are used by the imap code to display progress/status/error messages # -imapAlertDialogTitle = Alerta en la cuenta %S +#LOCALIZATION NOTE(imapAlertDialogTile): Do not translate the word "%S" +# below. Place the word %S where the account name should appear. +imapAlertDialogTitle=Alerta en la cuenta %S -imapStatusSelectingMailbox = Abriendo carpeta %S… +# Status - opening folder +imapStatusSelectingMailbox=Abriendo carpeta %S… -imapStatusCreatingMailbox = Creando carpeta… +# Status - create folder +imapStatusCreatingMailbox=Creando carpeta… -imapStatusDeletingMailbox = Eliminando carpeta %S… +# Status - deleting a folder +# LOCALIZATION NOTE (imapStatusDeletingMailbox): The "%S" below should not be translated. +# Instead, insert "%S" in your translation where you wish to display the name +# of the folder being deleted. +imapStatusDeletingMailbox=Eliminando carpeta %S… -imapStatusRenamingMailbox = Renombrando carpeta %S… +# Status - renaming mailbox +# LOCALIZATION NOTE (imapStatusRenamingMailbox): The "%S" below should not be translated. +# Instead, insert "%S" in your translation where you wish to display the name +# of the folder being renamed. +imapStatusRenamingMailbox=Renombrando carpeta %S… -imapStatusLookingForMailbox = Buscando carpetas… +# Status - looking for mailboxes +imapStatusLookingForMailbox=Buscando carpetas… -imapStatusSubscribeToMailbox = Suscribiéndose a la carpeta %S… +# Status - subscribing to mailbox +# LOCALIZATION NOTE (imapStatusSubscribeToMailbox): The "%S" below should not be translated. +# Instead, insert "%S" in your translation where you wish to display the name +# of the folder being subscribed to. +imapStatusSubscribeToMailbox=Suscribiéndose a la carpeta %S… -imapStatusUnsubscribeMailbox = Cancelando suscripción a la carpeta %S… +# Status - unsubscribing from mailbox +# LOCALIZATION NOTE (imapStatusUnsubscribeMailbox): The "%S" below should not be translated. +# Instead, insert "%S" in your translation where you wish to display the name +# of the folder being unsubscribed from. +imapStatusUnsubscribeMailbox=Cancelando suscripción a la carpeta %S… -imapStatusSearchMailbox = Buscando carpeta… +# Status - searching imap folder +imapStatusSearchMailbox=Buscando carpeta… -imapStatusCloseMailbox = Cerrando carpeta… +# Status - closing a folder +imapStatusCloseMailbox=Cerrando carpeta… -imapStatusExpungingMailbox = Comprimiendo carpeta… +# Status - compacting a folder +imapStatusExpungingMailbox=Comprimiendo carpeta… -imapStatusLoggingOut = Cerrando sesión… +# Status - logging out +imapStatusLoggingOut=Cerrando sesión… -imapStatusCheckCompat = Comprobando las características del servidor de correo… +# Status - checking server capabilities +imapStatusCheckCompat=Comprobando las características del servidor de correo… -imapStatusSendingLogin = Enviando información de conexión… +# Status - logging on +imapStatusSendingLogin=Enviando información de conexión… -imapStatusSendingAuthLogin = Enviando información de conexión… +# Status - auth logon +imapStatusSendingAuthLogin=Enviando información de conexión… -imapDownloadingMessage = Descargando mensaje… +imapDownloadingMessage=Descargando mensaje… -imapGettingACLForFolder = Obteniendo carpeta ACL… +# LOCALIZATION NOTE (imapGettingACLForFolder): Do not translate the word "ACL" below. +imapGettingACLForFolder=Obteniendo carpeta ACL… -imapGettingServerInfo = Obteniendo información sobre el servidor… +imapGettingServerInfo=Obteniendo información sobre el servidor… -imapGettingMailboxInfo = Obteniendo información sobre el buzón… +imapGettingMailboxInfo=Obteniendo información sobre el buzón… -imapEmptyMimePart = Esta parte del cuerpo del mensaje se descargará bajo demanda. +imapEmptyMimePart=Esta parte del cuerpo del mensaje se descargará bajo demanda. -imapReceivingMessageHeaders3 = Descargando cabecera de mensaje %1$S de %2$S en %3$S… +# LOCALIZATION NOTE (imapReceivingMessageHeaders3): Do not translate the words "%1$S", "%2$S", and "%3$S" below. +# Place the word %1$S in your translation where the number of the header being downloaded should appear. +# Place the word %2$S in your translation where the total number of headers to be downloaded should appear. +# Place the word %3$S in your translation where the name of the folder being processed should appear. +# Note: The account name and separators (e.g. colon, space) are automatically added to the status message. +# Example: "Joe's Account: Downloading message header 100 of 1000 in Drafts…" +imapReceivingMessageHeaders3=Descargando cabecera de mensaje %1$S de %2$S en %3$S… -imapReceivingMessageFlags3 = Descargando marca de mensaje %1$S de %2$S en %3$S… +# LOCALIZATION NOTE (imapReceivingMessageFlags3): Do not translate the words "%1$S", "%2$S", and "%3$S" below. +# Place the word %1$S in your translation where the number of the flag being downloaded should appear. +# Place the word %2$S in your translation where the total number of flags to be downloaded should appear. +# Place the word %3$S in your translation where the name of the folder being processed should appear. +# Note: The account name and separators (e.g. colon, space) are automatically added to the status message. +# Example: "Jim's Account: Downloading message flag 100 of 1000 in INBOX…" +imapReceivingMessageFlags3=Descargando marca de mensaje %1$S de %2$S en %3$S… -imapDeletingMessages = Eliminando mensajes… +imapDeletingMessages=Eliminando mensajes… -imapDeletingMessage = Eliminando mensaje… +imapDeletingMessage=Eliminando mensaje… -imapMovingMessages = Moviendo mensajes a %S… +# LOCALIZATION NOTE (imapMovingMessages): Do not translate the word "%S" below. +# Place the word %S in your translation where the name of the folder should appear. +imapMovingMessages=Moviendo mensajes a %S… -imapMovingMessage = Moviendo mensaje a %S… +# LOCALIZATION NOTE (imapMovingMessage): Do not translate the word "%S" below. +# Place the word %S in your translation where the name of the folder should appear. +imapMovingMessage=Moviendo mensaje a %S… -imapCopyingMessages = Copiando mensajes a %S… +# LOCALIZATION NOTE (imapCopyingMessages): Do not translate the word "%S" below. +# Place the word %S in your translation where the name of the folder should appear. +imapCopyingMessages=Copiando mensajes a %S… -imapCopyingMessage = Copiando mensaje a %S… +# LOCALIZATION NOTE (imapCopyingMessage): Do not translate the word "%S" below. +# Place the word %S in your translation where the name of the folder should appear. +imapCopyingMessage=Copiando mensaje a %S… -imapFolderReceivingMessageOf3 = Descargando mensaje %1$S de %2$S en %3$S… +# LOCALIZATION NOTE (imapFolderReceivingMessageOf3): Do not translate the words "%1$S", "%2$S", and "%3$S" below. +# Place the word %1$S in your translation where the number of the message being downloaded should appear. +# Place the word %2$S in your translation where the total number of messages to be downloaded should appear. +# Place the word %3$S in your translation where the name of the folder being processed should appear. +# Note: The account name and separators (e.g. colon, space) are automatically added to the status message. +# Example: "Juan's Account: Downloading message 100 of 1000 in Sent…" +imapFolderReceivingMessageOf3=Descargando mensaje %1$S de %2$S en %3$S… -imapDiscoveringMailbox = Encontrada la carpeta: %S +# LOCALIZATION NOTE (imapDiscoveringMailbox): Do not translate the word "%S" below. +# Place the word %S in your translation where the name of the folder should appear. +imapDiscoveringMailbox=Encontrada la carpeta: %S -imapEnterServerPasswordPrompt = Introduzca su contraseña para %1$S en %2$S: +# LOCALIZATION NOTE (imapEnterServerPasswordPrompt): Do not translate the words %1$S and %2$S below. +# Place the word %1$S in your translation where the username should appear. +# Place the word %2$S in your translation where the servername should appear. +imapEnterServerPasswordPrompt=Introduzca su contraseña para %1$S en %2$S: -imapServerNotImap4 = El servidor de correo %S no es un servidor de correo IMAP4. +# LOCALIZATION NOTE (imapServerNotImap4): Do not translate the word "IMAP4" below. +imapServerNotImap4=El servidor de correo %S no es un servidor de correo IMAP4. -imapDone = +# This is intentionally left blank. +imapDone= -imapEnterPasswordPromptTitleWithUsername = Introduzca su contraseña para %1$S +# LOCALIZATION NOTE (imapEnterPasswordPromptTitleWithUsername): Do not translate the +# word %1$S. Place the word %1$S where the user name should appear. +imapEnterPasswordPromptTitleWithUsername=Introduzca su contraseña para %1$S -imapUnknownHostError = No se pudo conectar con el servidor %S. -imapOAuth2Error = Fallo de identificación al conectarse al servidor %S. +imapUnknownHostError=No se pudo conectar con el servidor %S. +imapOAuth2Error=Fallo de identificación al conectarse al servidor %S. -imapConnectionRefusedError = No se ha podido conectar al servidor de correo %S: la conexión ha sido rechazada. +imapConnectionRefusedError=No se ha podido conectar al servidor de correo %S: la conexión ha sido rechazada. -imapNetTimeoutError = La conexión al servidor %S ha superado el tiempo de espera máximo. +imapNetTimeoutError=La conexión al servidor %S ha superado el tiempo de espera máximo. -imapNoNewMessages = No hay mensajes nuevos en el servidor. +imapTlsError=Ha ocurrido un error de TLS que no puede ser ignorado. Error de negociación o probablemente la versión del certificado usado por el servidor %S sea incompatible. -imapDefaultAccountName = Correo para %S +# Status - no messages to download +imapNoNewMessages=No hay mensajes nuevos en el servidor. -imapSpecialChar2 = El carácter %S está reservado en este servidor IMAP. Elija otro nombre. +imapDefaultAccountName=Correo para %S -imapPersonalSharedFolderTypeName = Carpeta personal +imapSpecialChar2=El carácter %S está reservado en este servidor IMAP. Elija otro nombre. -imapPublicFolderTypeName = Carpeta pública +imapPersonalSharedFolderTypeName=Carpeta personal -imapOtherUsersFolderTypeName = Carpeta de otro usuario +imapPublicFolderTypeName=Carpeta pública -imapPersonalFolderTypeDescription = Esta es una carpeta de correo personal. No está compartida. +imapOtherUsersFolderTypeName=Carpeta de otro usuario -imapPersonalSharedFolderTypeDescription = Esta es una carpeta de correo personal. Ha sido compartida. +imapPersonalFolderTypeDescription=Esta es una carpeta de correo personal. No está compartida. -imapPublicFolderTypeDescription = Esta es una carpeta pública. +imapPersonalSharedFolderTypeDescription=Esta es una carpeta de correo personal. Ha sido compartida. -imapOtherUsersFolderTypeDescription = Esta es una carpeta de correo compartida por el usuario '%S'. +imapPublicFolderTypeDescription=Esta es una carpeta pública. -imapAclFullRights = Control total +imapOtherUsersFolderTypeDescription=Esta es una carpeta de correo compartida por el usuario '%S'. -imapAclLookupRight = Buscar +imapAclFullRights=Control total -imapAclReadRight = Leer +imapAclLookupRight=Buscar -imapAclSeenRight = Cambiar estado Leído/No leído +imapAclReadRight=Leer -imapAclWriteRight = Escribir +imapAclSeenRight=Cambiar estado Leído/No leído -imapAclInsertRight = Insertar (copiar en) +imapAclWriteRight=Escribir -imapAclPostRight = Enviar +imapAclInsertRight=Insertar (copiar en) -imapAclCreateRight = Crear subcarpeta +imapAclPostRight=Enviar -imapAclDeleteRight = Eliminar mensajes +imapAclCreateRight=Crear subcarpeta -imapAclAdministerRight = Administrar carpeta +imapAclDeleteRight=Eliminar mensajes -imapServerDoesntSupportAcl = Este servidor no admite carpetas compartidas. +imapAclAdministerRight=Administrar carpeta -imapAclExpungeRight = Eliminar completamente +imapServerDoesntSupportAcl=Este servidor no admite carpetas compartidas. -imapServerDisconnected = El servidor %S ha cortado la conexión. Puede que el servidor se haya caído o que haya un problema en la red. +imapAclExpungeRight=Eliminar completamente -imapSubscribePrompt = ¿Quiere suscribirse a %1$S? +imapServerDisconnected= El servidor %S ha cortado la conexión. Puede que el servidor se haya caído o que haya un problema en la red. -imapServerDroppedConnection = No es posible conectar a su servidor IMAP. Puede que haya superado el número máximo de \ +# LOCALIZATION NOTE (autoSubscribeText): %1$S is the imap folder. +imapSubscribePrompt=¿Quiere suscribirse a %1$S? + +imapServerDroppedConnection=No es posible conectar a su servidor IMAP. Puede que haya superado el número máximo de \ conexiones a este servidor. Si es así, utilice el cuadro de diálogo de configuraciones \ avanzadas del servidor IMAP para reducir el número de conexiones cacheadas. -imapQuotaStatusFolderNotOpen = La información de cuota no está disponible porque la carpeta no está abierta. +# This will occur when a folder that has never been imap selected or opened +# (left-clicked) is first right-clicked to access quota properties. +imapQuotaStatusFolderNotOpen=La información de cuota no está disponible porque la carpeta no está abierta. -imapQuotaStatusNotSupported = Este servidor no incluye la característica de cuotas. +# The imap capability response reports that QUOTA is not supported. +imapQuotaStatusNotSupported=Este servidor no incluye la característica de cuotas. -imapQuotaStatusNoQuota2 = Esta carpeta no proporciona información de cuota. +# The getqutaroot command succeeded but reported no quota information. +imapQuotaStatusNoQuota2=Esta carpeta no proporciona información de cuota. -imapQuotaStatusInProgress = Información de cuota no disponible aún. +# Folder properties were requested by the user (right-click) before the getquotaroot +# command was sent. +imapQuotaStatusInProgress=Información de cuota no disponible aún. -imapOutOfMemory = La aplicación se ha quedado sin memoria. +# Out of memory +imapOutOfMemory=La aplicación se ha quedado sin memoria. -imapCopyingMessageOf2 = Copiando mensaje %1$S de %2$S a %3$S… +# LOCALIZATION NOTE (imapCopyingMessageOf2): Do not translate the word "%S" below. +# Place the word %3$S in your translation where the name of the destination folder should appear. +# Place the word %1$S where the currently copying message should appear. +# Place the word %2$S where the total number of messages should appear. +imapCopyingMessageOf2=Copiando mensaje %1$S de %2$S a %3$S… -imapMoveFolderToTrash = ¿Seguro que quiere eliminar la carpeta '%S'? +# LOCALIZATION NOTE (imapMoveFolderToTrash): Do not translate the word %S below. +# "%S" is the the name of the folder. +imapMoveFolderToTrash=¿Seguro que quiere eliminar la carpeta '%S'? -imapDeleteNoTrash = Eliminar esta carpeta no puede deshacerse y eliminará todos los mensajes que contiene y sus subcarpetas. ¿Aún está seguro de que quiere eliminar la carpeta '%S'? +# LOCALIZATION NOTE (imapDeleteNoTrash): Do not translate the word %S below. +# "%S" is the the name of the folder. +imapDeleteNoTrash=Eliminar esta carpeta no puede deshacerse y eliminará todos los mensajes que contiene y sus subcarpetas. ¿Aún está seguro de que quiere eliminar la carpeta '%S'? -imapDeleteFolderDialogTitle = Eliminar carpeta +imapDeleteFolderDialogTitle=Eliminar carpeta -imapDeleteFolderButtonLabel = &Eliminar carpeta +imapDeleteFolderButtonLabel=&Eliminar carpeta -imapAuthChangeEncryptToPlainSSL = El servidor IMAP %S no parece admitir contraseñas cifradas. Si acaba de configurar esta cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña normal' en 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, contacte con su proveedor o administrador de correo. +# LOCALIZATION NOTE (imapAuthChangeEncryptToPlainSSL): %S is the server hostname +imapAuthChangeEncryptToPlainSSL=El servidor IMAP %S no parece admitir contraseñas cifradas. Si acaba de configurar esta cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña normal' en 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, contacte con su proveedor o administrador de correo. -imapAuthChangePlainToEncrypt = El servidor IMAP %S no permite contraseñas sin cifrar. Intente cambiar a 'Contraseña cifrada' como 'Método de identificación' en la 'Configuración de cuentas | Configuración del servidor'. +# LOCALIZATION NOTE (imapAuthChangePlainToEncrypt): %S is the server hostname +imapAuthChangePlainToEncrypt=El servidor IMAP %S no permite contraseñas sin cifrar. Intente cambiar a 'Contraseña cifrada' como 'Método de identificación' en la 'Configuración de cuentas | Configuración del servidor'. -imapAuthChangeEncryptToPlainNoSSL = El servidor IMAP %S no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña, transmitida de forma insegura' en la 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, es un indicio de que alguien podría estar robándole la contraseña. +# LOCALIZATION NOTE (imapAuthChangeEncryptToPlainNoSSL): %S is the server hostname +imapAuthChangeEncryptToPlainNoSSL=El servidor IMAP %S no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña, transmitida de forma insegura' en la 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, es un indicio de que alguien podría estar robándole la contraseña. -imapAuthMechNotSupported = El servidor IMAP %S no admite el método de identificación seleccionado. Cambie el 'Método de identificación' en la 'Configuración de cuentas | Configuración del servidor'. +# LOCALIZATION NOTE (imapAuthMechNotSupported): %S is the server hostname +imapAuthMechNotSupported=El servidor IMAP %S no admite el método de identificación seleccionado. Cambie el 'Método de identificación' en la 'Configuración de cuentas | Configuración del servidor'. -imapAuthGssapiFailed = El tique Kerberos/GSSAPI no ha sido aceptado por el servidor IMAP %S. Compruebe que ha iniciado sesión en el dominio Kerberos/GSSAPI. +# LOCALIZATION NOTE (imapAuthGssapiFailed): %S is the server hostname +imapAuthGssapiFailed=El tique Kerberos/GSSAPI no ha sido aceptado por el servidor IMAP %S. Compruebe que ha iniciado sesión en el dominio Kerberos/GSSAPI. -imapServerCommandFailed = La orden actual no se ejecutó con éxito. El servidor de correo de la cuenta %1$S respondió: %2$S +# LOCALIZATION NOTE (imapServerCommandFailed): +# Place the word %1$S in your translation where the name of the account name should appear. +# Place the word %2$S in your translation where the server response should appear. +imapServerCommandFailed=La orden actual no se ejecutó con éxito. El servidor de correo de la cuenta %1$S respondió: %2$S -imapFolderCommandFailed = La operación actual en '%2$S' no se ejecutó con éxito. El servidor de correo de la cuenta %1$S respondió: %3$S +# LOCALIZATION NOTE (imapFolderCommandFailed): Do not translate the word %S below. +# Place the word %1$S in your translation where the name of the account should appear. +# Place the word %2$S in your translation where the name of the folder should appear. +# Place the word %3$S in your translation where the server response should appear. +imapFolderCommandFailed=La operación actual en '%2$S' no se ejecutó con éxito. El servidor de correo de la cuenta %1$S respondió: %3$S -imapServerAlert = Alerta de la cuenta %1$S: %2$S +# LOCALIZATION NOTE (imapServerAlert): +# Place the word %1$S in your translation where the name of the account should appear. +# Place the word %2$S in your translation where the alert from the server should appear. +imapServerAlert=Alerta de la cuenta %1$S: %2$S diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/localMsgs.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/localMsgs.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/localMsgs.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/localMsgs.properties 2022-04-15 07:52:23.000000000 +0000 @@ -6,76 +6,135 @@ # The following are used by the local mail code to display progress/status/error messages # -pop3ErrorDialogTitle = Error en la cuenta %S +# LOCALIZATION NOTE(pop3ErrorDialogTitle): Do not translate the word "%S" +# below. Place the word %S where the account name should appear. +pop3ErrorDialogTitle=Error en la cuenta %S -pop3EnterPasswordPromptTitleWithUsername = Introduzca su contraseña para %1$S +# LOCALIZATION NOTE (pop3EnterPasswordPromptTitleWithUsername): Do not translate the +# word %1$S. Place the word %1$S where the user name should appear. +pop3EnterPasswordPromptTitleWithUsername=Introduzca su contraseña para %1$S -pop3EnterPasswordPrompt = Introduzca su contraseña para %1$S en %2$S: +# LOCALIZATION NOTE(pop3EnterPasswordPrompt): Do not translate the words "%1$S" +# and "%2$S" below. Place the word %1$S where the user name should appear, and +# %2$S where the host name should appear. +pop3EnterPasswordPrompt=Introduzca su contraseña para %1$S en %2$S: -pop3PreviouslyEnteredPasswordIsInvalidPrompt = Introduzca una nueva contraseña para el usuario %1$S en %2$S: +# LOCALIZATION NOTE(pop3PreviouslyEnteredPasswordIsInvalidPrompt): Do not +# translate the words "%1$S" and "%2$S" below. Place the word %1$S where the +# user name should appear, and %2$S where the host name should appear. +pop3PreviouslyEnteredPasswordIsInvalidPrompt=Introduzca una nueva contraseña para el usuario %1$S en %2$S: -receivingMessages = Descargando mensaje %1$S de %2$S… +# Status - Downloading message n of m +# LOCALIZATION NOTE (receivingMessages): Do not translate %1$S or %2$S in the following lines. +# Place the word %1$S where the number of messages downloaded so far should appear. +# Place the word %2$S where the total number of messages to receive should appear; +receivingMessages=Descargando mensaje %1$S de %2$S… -hostContact = Servidor contactado, enviando información de inicio de sesión… +# Status - connecting to host +hostContact=Servidor contactado, enviando información de inicio de sesión… -noNewMessages = No hay mensajes nuevos. +# Status - no messages to download +noNewMessages=No hay mensajes nuevos. -receivedMsgs = Recibidos %1$S de %2$S mensajes +# Status - messages received after the download +#LOCALIZATION NOTE : Do not translate %1$S or %2$S in the following line. +# %1$S will receive the number of messages received +# %2$S will receive the total number of messages +receivedMsgs=Recibidos %1$S de %2$S mensajes -buildingSummary = Construyendo archivo de resumen de %S… +# Status - parsing folder +#LOCALIZATION NOTE (buildingSummary): Do not translate %S in the following line. +# Place the word %S where the name of the mailbox should appear +buildingSummary=Construyendo archivo de resumen de %S… -localStatusDocumentDone = Hecho +# Status - parsing folder +localStatusDocumentDone=Hecho -pop3ServerError = Se ha producido un error en la conexión el servidor de correo POP3. +# Status - pop3 server error +#LOCALIZATION NOTE (pop3ServerError): Do not translate POP3 in the following line. +pop3ServerError=Se ha producido un error en la conexión el servidor de correo POP3. -pop3UsernameFailure = Se produjo un error al enviar el nombre de usuario. +# Status - pop3 user name failed +pop3UsernameFailure=Se produjo un error al enviar el nombre de usuario. -pop3PasswordFailed = El envío de la contraseña para el usuario %1$S no se completó con éxito. +# Status - password failed +#LOCALIZATION NOTE (pop3PasswordFailed): Do not translate "%1$S" below. +# Place the word %1$S where the user name should appear. +pop3PasswordFailed=El envío de la contraseña para el usuario %1$S no se completó con éxito. -pop3MessageWriteError = No se puede guardar el mensaje en el buzón de correo. Compruebe que tiene permiso de escritura en el directorio y suficiente espacio en disco para copiar el buzón de correo. +# Status - write error occurred +pop3MessageWriteError=No se puede guardar el mensaje en el buzón de correo. Compruebe que tiene permiso de escritura en el directorio y suficiente espacio en disco para copiar el buzón de correo. -pop3RetrFailure = El comando RETR no se completó con éxito. Error al recuperar el mensaje. +# Status - retr failure from the server +pop3RetrFailure=El comando RETR no se completó con éxito. Error al recuperar el mensaje. -pop3PasswordUndefined = Error al obtener la contraseña de correo. +# Status - password undefined +pop3PasswordUndefined=Error al obtener la contraseña de correo. -pop3UsernameUndefined = No ha especificado el usuario para este servidor. Indique uno en el menú de configuración de la cuenta y vuelva a intentarlo. +# Status - username undefined +pop3UsernameUndefined=No ha especificado el usuario para este servidor. Indique uno en el menú de configuración de la cuenta y vuelva a intentarlo. -pop3ListFailure = El comando LIST no se completó con éxito. Error al obtener el ID y tamaño de un mensaje. +# Status - list failure +pop3ListFailure=El comando LIST no se completó con éxito. Error al obtener el ID y tamaño de un mensaje. -pop3DeleFailure = El comando DELE no se completó con éxito. Error al marcar un mensaje como eliminado. +# Status - delete error +pop3DeleFailure=El comando DELE no se completó con éxito. Error al marcar un mensaje como eliminado. -pop3StatFail = El comando STAT no se completó con éxito. Error al obtener el número de mensajes y sus tamaños. +# Status - stat failed +pop3StatFail=El comando STAT no se completó con éxito. Error al obtener el número de mensajes y sus tamaños. -pop3ServerSaid = El servidor de correo %S respondió: +#LOCALIZATION NOTE (pop3ServerSaid): Do not remove the leading space during translation. +pop3ServerSaid= El servidor de correo %S respondió: -copyingMessagesStatus = Copiando %S de %S mensajes a %S +#LOCALIZATION NOTE (pop3TempServerError): %S is where the POP3 server name will appear. +pop3TempServerError=Error temporal de %S al recuperar nuevos mensajes. \ +La operación se volverá a intentar la próxima vez que se busquen nuevos mensajes. -movingMessagesStatus = Moviendo %S de %S mensajes a %S +copyingMessagesStatus=Copiando %S de %S mensajes a %S -pop3ServerBusy = La cuenta %S está siendo procesada. Espere hasta que termine el proceso para obtener los mensajes. +movingMessagesStatus=Moviendo %S de %S mensajes a %S -pop3TmpDownloadError = Hubo un error al descargar el siguiente mensaje: \nDe: %S\n Asunto: %S\n Puede que este mensaje contenga un virus o que no haya suficiente espacio en disco. ¿Saltarse este mensaje? +# Status - pop3 server or folder busy +# LOCALIZATION NOTE (pop3ServerBusy): Do not translate the word "%S" below. +# Place %S where the account name should appear. +pop3ServerBusy=La cuenta %S está siendo procesada. Espere hasta que termine el proceso para obtener los mensajes. -pop3ServerDoesNotSupportUidlEtc = El servidor de correo POP3 (%S) no admite UIDL ni XTND XLST, necesario para implementar las opciones ``Dejar en el servidor'', ``Tamaño máximo de mensaje'' o ``Descargar sólo cabeceras''. Para descargar su mensaje, desactive estas opciones en la configuración de servidor de su servidor de correo en la ventana Configuración de cuentas. +pop3TmpDownloadError=Hubo un error al descargar el siguiente mensaje: \nDe: %S\n Asunto: %S\n Puede que este mensaje contenga un virus o que no haya suficiente espacio en disco. ¿Saltarse este mensaje? -pop3ServerDoesNotSupportTopCommand = El servidor de correo POP3 (%S) no admite el comando TOP. Si el servidor no lo admite, no se puede implementar la preferencia ``Tamaño máximo de mensaje'' o ``Descargar sólo cabeceras''. Esta opción se ha desactivado y todos los mensajes se recibirán sin tener en cuenta su tamaño. +# Status - the server doesn't support UIDL… +# LOCALIZATION NOTE(pop3ServerDoesNotSupportUidlEtc): The following sentence should be translated in this way: +# Do not translate "POP3" +# Do not translate "%S". Place %S in your translation where the name of the server should appear. +# Do not translate "UIDL" +pop3ServerDoesNotSupportUidlEtc=El servidor de correo POP3 (%S) no admite UIDL ni XTND XLST, necesario para implementar las opciones ``Dejar en el servidor'', ``Tamaño máximo de mensaje'' o ``Descargar sólo cabeceras''. Para descargar su mensaje, desactive estas opciones en la configuración de servidor de su servidor de correo en la ventana Configuración de cuentas. -nsErrorCouldNotConnectViaTls = No se puede establecer una conexión TLS con el servidor POP3. El servidor puede estar caído o configurado incorrectamente. Verifique la configuración correcta en las opciones de servidor de su servidor de correo en la ventana Configuración de cuentas y vuelva a intentarlo. +# Status - the server doesn't support the top command +# LOCALIZATION NOTE(pop3ServerDoesNotSupportTopCommand): The following sentence should be translated in this way: +# Do not translate "POP3" +# Do not translate "%S". Place %S in your translation where the name of the server should appear. +# Do not translate "TOP" +pop3ServerDoesNotSupportTopCommand=El servidor de correo POP3 (%S) no admite el comando TOP. Si el servidor no lo admite, no se puede implementar la preferencia ``Tamaño máximo de mensaje'' o ``Descargar sólo cabeceras''. Esta opción se ha desactivado y todos los mensajes se recibirán sin tener en cuenta su tamaño. -pop3MoveFolderToTrash = ¿Seguro que quiere eliminar la carpeta '%S'? +nsErrorCouldNotConnectViaTls=No se puede establecer una conexión TLS con el servidor POP3. El servidor puede estar caído o configurado incorrectamente. Verifique la configuración correcta en las opciones de servidor de su servidor de correo en la ventana Configuración de cuentas y vuelva a intentarlo. -pop3DeleteFolderDialogTitle = Eliminar carpeta +# LOCALIZATION NOTE (pop3MoveFolderToTrash): Do not translate the word %S below. +# "%S" is the the name of the folder. +pop3MoveFolderToTrash=¿Seguro que quiere eliminar la carpeta '%S'? -pop3DeleteFolderButtonLabel = &Eliminar carpeta +pop3DeleteFolderDialogTitle=Eliminar carpeta -pop3AuthInternalError = Error interno de estado durante la identificación ante el servidor POP3. Éste es un error interno e inesperado en la aplicación, informe del mismo como un bug. +pop3DeleteFolderButtonLabel=&Eliminar carpeta -pop3AuthChangeEncryptToPlainNoSSL = Este servidor POP3 no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña, transmitida de forma insegura' en la 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, es un indicio de que alguien podría estar robándole la contraseña. +pop3AuthInternalError=Error interno de estado durante la identificación ante el servidor POP3. Éste es un error interno e inesperado en la aplicación, informe del mismo como un bug. -pop3AuthChangeEncryptToPlainSSL = Este servidor POP3 no parece admitir contraseñas cifradas. Si acaba de configurar esta cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña normal' en 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, contacte con su proveedor o administrador de correo. +pop3AuthChangeEncryptToPlainNoSSL=Este servidor POP3 no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña, transmitida de forma insegura' en la 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, es un indicio de que alguien podría estar robándole la contraseña. -pop3AuthChangePlainToEncrypt = Este servidor POP3 no admite contraseñas sin cifrar. Intente cambiar el 'Método de identificación' a 'Contraseña cifrada' en la 'Configuración de cuentas | Configuración del servidor'. +pop3AuthChangeEncryptToPlainSSL=Este servidor POP3 no parece admitir contraseñas cifradas. Si acaba de configurar esta cuenta, pruebe a cambiar el 'Método de identificación' a 'Contraseña normal' en 'Configuración de cuentas | Configuración del servidor'. Si solía funcionar y ahora de pronto falla, contacte con su proveedor o administrador de correo. -pop3AuthMechNotSupported = El servidor no admite el método de identificación seleccionado. Cambie el 'Método de identificación' en la 'Configuración de cuentas | Configuración del servidor'. +pop3AuthChangePlainToEncrypt=Este servidor POP3 no admite contraseñas sin cifrar. Intente cambiar el 'Método de identificación' a 'Contraseña cifrada' en la 'Configuración de cuentas | Configuración del servidor'. -pop3GssapiFailure = El tique Kerberos/GSSAPI no ha sido aceptado por el servidor POP. Compruebe que ha iniciado sesión en el dominio Kerberos/GSSAPI. +# Authentication server caps and pref don't match +pop3AuthMechNotSupported=El servidor no admite el método de identificación seleccionado. Cambie el 'Método de identificación' en la 'Configuración de cuentas | Configuración del servidor'. + +# Status - Could not log in to GSSAPI, and it was the only method +pop3GssapiFailure=El tique Kerberos/GSSAPI no ha sido aceptado por el servidor POP. Compruebe que ha iniciado sesión en el dominio Kerberos/GSSAPI. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messengercompose/composeMsgs.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messengercompose/composeMsgs.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messengercompose/composeMsgs.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messengercompose/composeMsgs.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,303 +2,479 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -unableToOpenFile = No se puede abrir el archivo %S. -unableToOpenTmpFile = No se puede abrir el archivo temporal %S. Compruebe la configuración de su 'directorio temporal'. -unableToSaveTemplate = No es posible guardar su mensaje como plantilla. -unableToSaveDraft = No es posible guardar su mensaje como un borrador. -couldntOpenFccFolder = No se puede abrir la carpeta Enviados. Verifique que la configuración de su cuenta es correcta. -noSender = No se ha indicado remitente. Añada su dirección de correo en la configuración de la cuenta. -noRecipients = No se especificaron destinatarios. Introduzca un destinatario o grupo de noticias en el área de dirección. -errorWritingFile = Error al escribir el archivo temporal. - -errorSendingFromCommand = Ocurrió un error mientras se enviaba el correo. El servidor de correo respondió: %s. Verifique que su dirección de correo electrónico es correcta en las preferencias de su cuenta y vuelva a intentarlo. - -errorSendingDataCommand = Ocurrió un error en el servidor de salida (SMTP) al enviar el correo. El servidor respondió: %s. - -errorSendingMessage = Ocurrió un error al enviar el correo. El servidor de correo respondió: %s. Compruebe el mensaje y vuelva a intentarlo. -postFailed = No se ha podido publicar el mensaje porque ha fallado la conexión al servidor de noticias. El servidor puede no estar disponible o está rechazando conexiones. Verifique que la configuración de su servidor de noticias es correcta y vuelva a intentarlo. -errorQueuedDeliveryFailed = Ocurrió un error al procesar sus mensajes no enviados. -sendFailed = Falló el envío del mensaje. - -sendFailedUnexpected = Envío fallido debido al error inesperado %X. No hay ninguna descripción disponible. - -smtpSecurityIssue = La configuración relacionada con %S debe corregirse. - -smtpServerError = Ha sucedido un error al enviar el correo: error en el servidor de salida (SMTP). El servidor respondió: %s. -unableToSendLater = Lo sentimos, no hemos podido guardar su mensaje para enviarlo más tarde. - -communicationsError = Ocurrió un error de comunicación: %d. Vuelva a intentarlo. -dontShowAlert = ESTO ES SOLO UNA RESERVA DE ESPACIO. NUNCA DEBERÍA VER ESTE TEXTO. - -couldNotGetUsersMailAddress2 = Ha sucedido un error al enviar el correo: la dirección del remitente (De:) no es válida. Verifique que esta dirección de correo es correcta y vuelva a intentarlo. -couldNotGetSendersIdentity = Ha sucedido un error al enviar el correo: la identidad del remitente no es válida. Verifique la configuración de su identidad y vuelva a intentarlo. - -mimeMpartAttachmentError = Error en adjunto. -failedCopyOperation = El mensaje se envió con éxito, pero la copia a la carpeta Enviados falló. -nntpNoCrossPosting = Sólo puede enviar un mensaje a un servidor de noticias a la vez. -msgCancelling = Cancelando… -sendFailedButNntpOk = Su mensaje ha sido enviado al grupo de noticias pero no ha sido enviado al otro destinatario. -errorReadingFile = Error leyendo el archivo. -followupToSenderMessage = El autor de este mensaje ha pedido que las respuestas sean enviadas únicamente al autor. Si también quiere responder al grupo de noticias, añada una nueva fila en el area de direcciones, elija Grupo de la lista de cabeceras, e introduzca el nombre del grupo de noticias. - -errorAttachingFile = Ha habido un problema al adjuntar %S. Compruebe si tiene acceso al archivo. - -incorrectSmtpGreeting = Ocurrió un error al enviar el correo: el servidor de correo envió un saludo incorrecto: %s. - -errorSendingRcptCommand = Ha ocurrido un error al enviar el mensaje. El servidor de correo respondió: \n%1$S.\nVerifique el destinatario "%2$S" y vuelva a intentarlo. - -startTlsFailed = Ha ocurrido un error al enviar el mensaje: no es posible establecer un enlace seguro con el servidor de salida (SMTP) %S usando STARTTLS ya que no anuncia ese mecanismo. Desactive STARTTLS para ese servidor o contacte con su proveedor del servicio. - -smtpPasswordUndefined = Ha ocurrido un error al enviar el mensaje: no se ha podido obtener la contraseña para %S. El mensaje no se ha enviado. - -smtpSendNotAllowed = Ha ocurrido un error al enviar el mensaje. El servidor de correo ha respondido:\n%s.\nAsegúrese de que está usando la identidad correcta para el envío y el método de identificación usado es correcto. Verifique está autorizado a enviar a través de este servidor SMTP con sus credenciales actuales de la red que está usando ahora. - -smtpTempSizeExceeded = El tamaño del mensaje que está intentando enviar excede un límite temporal de tamaño del servidor. El mensaje no se ha enviado; intente reducir el tamaño del mensaje o espere un rato y vuelva a intentarlo. El servidor respondió: %s. - -smtpClientid = El servidor de salida (SMTP) ha detectado un error en la orden CLIENTID. No se ha enviado el mensaje. El servidor ha respondido: %s - -smtpClientidPermission = La respuesta del servidor de salida (SMTP) a la orden CLIENTID indica que su dispositivo no tiene permitido enviar correo. El servidor ha respondido: %s - -smtpPermSizeExceeded1 = El tamaño del mensaje que está intentando enviar excede el límite global de tamaño (%d bytes) del servidor. El mensaje no se ha enviado; reduzca el tamaño del mensaje y vuelva a intentarlo. - -smtpPermSizeExceeded2 = El tamaño del mensaje que está intentando enviar excede el límite global de tamaño del servidor. El mensaje no se ha enviado; reduzca el tamaño del mensaje y vuelva a intentarlo. El servidor respondió: %s. - -smtpSendFailedUnknownServer = Ha ocurrido un error al enviar el mensaje: el servidor de salida (SMTP) %S es desconocido. El servidor puede estar mal configurado. Verifique que la configuración de su servidor de salida (SMTP) es correcta y vuelva a intentarlo. - -smtpSendRequestRefused = El mensaje no se ha podido enviar porque ha fallado la conexión al servidor de salida (SMTP) %S. El servidor puede no estar disponible o está rechazando conexiones SMTP. Verifique que los ajustes de su servidor de salida (SMTP) son correctos y vuelva a intentarlo. - -smtpSendInterrupted = El mensaje no se ha podido enviar porque la conexión al servidor de salida (SMTP) %S se perdió en mitad de la transacción. Vuelva a intentarlo. - -smtpSendTimeout = El mensaje no se ha podido enviar porque ha caducado la conexión al servidor de salida (SMTP) %S. Vuelva a intentarlo. - -smtpSendFailedUnknownReason = El mensaje no se ha podido enviar usando el servidor de salida (SMTP) %S por una razón desconocida. Verifique que los ajustes de su servidor de salida (SMTP) son correctos y vuelva a intentarlo. - -smtpHintAuthEncryptToPlainNoSsl = El servidor de salida (SMTP) %S no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)' a 'Contraseña, transmitida de forma insegura'. Si antes funcionaba pero ya no, puede que se le haya sustraído su contraseña. - -smtpHintAuthEncryptToPlainSsl = El servidor de salida (SMTP) %S no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)' a 'Contraseña normal'. - -smtpHintAuthPlainToEncrypt = El servidor de salida (SMTP) %S no admite contraseñas no cifradas. Pruebe a cambiar el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)' a 'Contraseña cifrada'. - -smtpAuthFailure = No se puede identificar al servidor de salida (SMTP) %S. Compruebe la contraseña y verifique el 'Método de identificación' en 'Configuración de cuentas | Servidor de salida (SMTP)'. - -smtpAuthGssapi = El tique Kerberos/GSSAPI no ha sido aceptado por el servidor de salida (SMTP) %S. Compruebe que ha iniciado sesión en el dominio Kerberos/GSSAPI. - -smtpAuthMechNotSupported = El servidor de salida (SMTP) %S no admite el mecanismo de identificación seleccionado. Cambie el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)'. - -saveDlogTitle = Guardar mensaje - -saveDlogMessages3 = ¿Guardar este mensaje en su carpeta de borradores (%1$S) y cerrar la ventana de redacción? -discardButtonLabel = &Descartar cambios - -defaultSubject = (sin asunto) -chooseFileToAttach = Adjuntar archivo(s) -genericFailureExplanation = Verifique que la configuración de su cuenta es correcta y vuelva a intentarlo. - -undisclosedRecipients = destinatarios-no-revelados - -chooseFileToAttachViaCloud = Adjuntar archivo(s) a través de %1$S - -windowTitleWrite = Escribir: %1$S - %2$S -windowTitlePrintPreview = Vista preliminar: %1$S - %2$S - -msgIdentityPlaceholder = Introduzca la dirección Desde personalizada que quiere usar en lugar de %S -customizeFromAddressTitle = Personalizar dirección De -customizeFromAddressWarning = Si su proveedor de correo lo admite, Personalizar dirección De le permite hacer una alteración menor puntual a su dirección de remite sin tener que crear una nueva identidad en la configuración de cuentas. Por ejemplo, si su dirección de remite es Juan Pérez puede que quiera cambiarlo a Juan Pếrez o Juan . -customizeFromAddressIgnore = No volver a avisarme de nuevo - -subjectEmptyTitle = Recordatorio de asunto -subjectEmptyMessage = Su mensaje no tiene asunto. -sendWithEmptySubjectButton = &Enviar sin asunto -cancelSendingButton = &Cancelar envío - -noNewsgroupSupportTitle = Grupos de noticias no admitidos -recipientDlogMessage = Esta cuenta sólo soporta destinatarios de correo. Continuar ignorará los grupos de noticias. - -addressInvalidTitle = Dirección de destinatario no válida -addressInvalid = %1$S no es una dirección de correo electrónico válida porque no tiene la forma usuario@dominio. Debe corregirse antes de enviar el correo. - -attachPageDlogTitle = Especifique qué dirección desea adjuntar -attachPageDlogMessage = Página web (URL): - -messageAttachmentSafeName = Mensaje adjunto - -partAttachmentSafeName = Parte del mensaje adjunto - -attachmentBucketAttachFilesTooltip = Adjuntar archivo(s) -attachmentBucketClearSelectionTooltip = Limpiar selección -attachmentBucketHeaderShowTooltip = Mostrar el panel de adjuntos -attachmentBucketHeaderMinimizeTooltip = Minimizar panel de adjuntos -attachmentBucketHeaderRestoreTooltip = Restaurar panel de adjuntos - -initErrorDlogTitle = Redacción de mensaje -initErrorDlgMessage = Ha sucedido un error al crear una ventana de redacción de mensajes. Vuelva a intentarlo. - -errorFileAttachTitle = Anexado de archivo - -errorFileAttachMessage = El archivo %1$S no existe por lo que no ha podido adjuntarse al mensaje. - -errorFileMessageTitle = Archivo de mensajes - -errorFileMessageMessage = El archivo %1$S no existe y no se ha podido usar como contenido del mensaje. - -errorLoadFileMessageMessage = No se ha podido cargar el archivo %1$S como contenido del mensaje. - -SaveDialogTitle = Guardar mensaje - -SaveDialogMsg = Su mensaje se ha guardado en la carpeta %1$S en %2$S. -CheckMsg = No volver a mostrarme esta ventana de diálogo. - -quitComposeWindowTitle = Enviando mensaje - -quitComposeWindowMessage2 = %1$S está actualmente enviando un mensaje.\n¿Quiere salir ahora, o esperar hasta que el mensaje haya sido enviado antes de salir? -quitComposeWindowQuitButtonLabel2 = &Salir -quitComposeWindowWaitButtonLabel2 = &Esperar -quitComposeWindowSaveTitle = Guardando mensaje - -quitComposeWindowSaveMessage = %1$S está actualmente guardando un mensaje.\n¿Quiere salir ahora, o esperar hasta que el mensaje haya sido guardado antes de salir? - -sendMessageCheckWindowTitle = Enviar mensaje -sendMessageCheckLabel = ¿Seguro que está preparado para mandar este mensaje? -sendMessageCheckSendButtonLabel = Enviar -assemblingMessageDone = Ensamblando el mensaje… Listo -assemblingMessage = Ensamblando el mensaje… -smtpDeliveringMail = Enviando correo… -smtpMailSent = Correo enviado con éxito -assemblingMailInformation = Ensamblando la información de correo… - -gatheringAttachment = Adjuntando %S… -creatingMailMessage = Creando mensaje de correo… - -copyMessageStart = Copiando el mensaje a la carpeta %S… -copyMessageComplete = Copia completada. -copyMessageFailed = Falló la copia. -filterMessageComplete = Filtro completo. -filterMessageFailed = Filtro fallido. - -largeMessageSendWarning = ¡Advertencia! Está a punto de enviar un mensaje de tamaño %S. ¿Está seguro de que quiere hacerlo? -sendingMessage = Enviando el mensaje… -sendMessageErrorTitle = Error de envío de mensaje -postingMessage = Publicando el mensaje… -sendLaterErrorTitle = Error de envío posterior -saveDraftErrorTitle = Error guardando el borrador -saveTemplateErrorTitle = Error guardando la plantilla - -failureOnObjectEmbeddingWhileSaving = Hubo un problema al incluir el archivo %.200S en el mensaje. ¿Quiere seguir guardando el mensaje sin el archivo? - -failureOnObjectEmbeddingWhileSending = Hubo un problema al incluir el archivo %.200S en el mensaje. ¿Quiere continuar el envío del mensaje sin este archivo? -returnToComposeWindowQuestion = ¿Quiere volver a la ventana de redacción? - -mailnews.reply_header_authorwrotesingle = #1 escribió: - -mailnews.reply_header_ondateauthorwrote = El #2 a las #3, #1 escribió: - -mailnews.reply_header_authorwroteondate = #1 escribió el #2 a las #3: - -mailnews.reply_header_originalmessage = -------- Mensaje original -------- - -mailnews.forward_header_originalmessage = -------- Mensaje reenviado -------- - -renameAttachmentTitle = Renombrar adjunto -renameAttachmentMessage = Nuevo nombre del adjunto: - -mail.compose.attachment_reminder_keywords = adjunto,adjuntado,.doc,.pdf,.xls,.ppt,.rtf,.pps,currículum,CV,carta de presentación,envío - -remindLaterButton = Recordármelo más tarde -remindLaterButton.accesskey = R -disableAttachmentReminderButton = Desactivar recordatorio de adjuntos en el mensaje actual -attachmentReminderTitle = Recordatorio de adjuntos -attachmentReminderMsg = ¿Ha olvidado añadir un adjunto? - -attachmentReminderKeywordsMsgs = Encontrada una palabra clave de adjuntos:;Encontradas #1 palabras clave de adjuntos: -attachmentReminderOptionsMsg = Las palabras recordatorios de adjuntos se pueden configurar en sus preferencias -attachmentReminderYesIForgot = ¡Uups, sí, se me ha olvidado! -attachmentReminderFalseAlarm = No, enviar ahora - -learnMore.label = Saber más… -learnMore.accesskey = m - -bigFileDescription = Este archivo es grande. Podría ser mejor usar Filelink.;Estos archivos son grandes. Podría ser mejor usar Filelink. -bigFileShare.label = Enlazar -bigFileShare.accesskey = E -bigFileAttach.label = Ignorar -bigFileAttach.accesskey = I -bigFileChooseAccount.title = Elija una cuenta -bigFileChooseAccount.text = Elija una cuenta en la nube a la que subir el adjunto -bigFileHideNotification.title = No subir mis archivos -bigFileHideNotification.text = No se le avisará si adjunta más archivos grandes a este mensaje. -bigFileHideNotification.check = No volver a avisarme. - -cloudFileUploadingTooltip = Subiendo a %S… - -cloudFileUploadedTooltip = Subido a %S -cloudFileUploadingNotification = Su archivo está siendo enlazado. Aparecerá en el cuerpo del mensaje cuando esté completo.;Sus archivos están siendo enlazados. Aparecerán en el cuerpo del mensaje cuando estén completos. -cloudFileUploadingCancel.label = Cancelar -cloudFileUploadingCancel.accesskey = C -cloudFilePrivacyNotification = Enlazado completado. Tenga en cuenta que los adjuntos enlazados pueden ser accesibles a las personas que puedan ver o adivinar los enlaces. - -smtpEnterPasswordPrompt = Introduzca su contraseña para %S: - -smtpEnterPasswordPromptWithUsername = Introduzca la contraseña para %2$S en %1$S: - -smtpEnterPasswordPromptTitleWithHostname = Contraseña necesaria para el servidor saliente (SMTP) %1$S - -removeAttachmentMsgs = Eliminar adjunto;Eliminar adjuntos - -promptToSaveSentLocally2 = Su mensaje se ha enviado pero no se ha copiado a su carpeta de mensajes enviados (%1$S) debido a errores de red o acceso a archivos.\nPuede reintentar o guardar el mensaje en modo local a %3$S/%1$S-%2$S. -errorFilteringMsg = Su mensaje ha sido enviado y guardado, pero ha sucedido un error al aplicarle los filtros de mensajes. -errorCloudFileAuth.title = Error de identificación - -promptToSaveDraftLocally2 = Su borrador de mensaje no se ha copiado a su carpeta de borradores (%1$S) debido a errores de red o acceso a archivos.\nPuede reintentar o guardar el borrador en modo local a %3$S/%1$S-%2$S. -buttonLabelRetry2 = &Reintentar - -promptToSaveTemplateLocally2 = Su plantilla de mensaje no se ha copiado a su carpeta de plantillas (%1$S) debido a errores de red o acceso a archivos.\nPuede reintentar o guardar la plantilla en modo local a %3$S/%1$S-%2$S. - -saveToLocalFoldersFailed = No se puede guardar su mensaje en las carpetas locales. Posiblemente no disponga de espacio de almacenamiento suficiente. - -errorCloudFileAuth.message = No se puede iniciar sesión en %1$S. -errorCloudFileUpload.title = Error de subida - -errorCloudFileUpload.message = No se puede subir %2$S a %1$S. -errorCloudFileQuota.title = Error de cuota - -errorCloudFileQuota.message = Subir %2$S a %1$S excedería su cuota de espacio. -errorCloudFileNameLimit.title = Error en el nombre del archivo - -errorCloudFileNameLimit.message = %2$S contiene más de 120 caracteres en su nombre, lo que supera la longitud máxima de nombre de archivo para %1$S. Renombre el archivo para que su nombre tenga 120 caracteres o menos y súbalo de nuevo. -errorCloudFileLimit.title = Error en el tamaño del archivo - -errorCloudFileLimit.message = %2$S excede el tamaño máximo para %1$S. -errorCloudFileOther.title = Error desconocido\u0020 - -errorCloudFileOther.message = Ha sucedido un error desconocido durante la comunicación con %1$S. -errorCloudFileDeletion.title = Error de borrado - -errorCloudFileDeletion.message = Ha sucedido un problema al eliminar %2$S de %1$S. -errorCloudFileUpgrade.label = Actualizar - -cloudAttachmentCountHeader = He enlazado #1 archivo a este mensaje:;He enlazado #1 archivos a este mensaje: - -cloudAttachmentListFooter = %1$S hace fácil compartir archivos grandes a través del correo electrónico. - -cloudAttachmentListItem = * %1$S (%2$S) alojado en %3$S: %4$S - -stopShowingUploadingNotification.accesskey = N -stopShowingUploadingNotification.label = No mostrar esto de nuevo -replaceButton.label = Reemplazar… -replaceButton.accesskey = R -replaceButton.tooltip = Mostrar el diálogo Buscar y reemplazar - -blockedAllowResource = Desbloquear %S -blockedContentMessage = %S ha bloqueado la carga de un archivo en este mensaje. Desbloquear el archivo lo incluirá en su mensaje enviado.;%S ha bloqueado la carga de algunos archivos en este mensaje. Desbloquear un archivo lo incluirá en su mensaje enviado. - -blockedContentPrefLabel = Opciones -blockedContentPrefAccesskey = O - -blockedContentPrefLabelUnix = Preferencias -blockedContentPrefAccesskeyUnix = P - -confirmRemoveRecipientRowTitle2 = Eliminar direcciones %S -confirmRemoveRecipientRowBody2 = ¿Está seguro de que quiere eliminar las direcciones %S? -confirmRemoveRecipientRowButton = Eliminar - -headersSpaceStyle = width: 8em +# +# The following are used by the compose back end +# +## LOCALIZATION NOTE (unableToOpenFile, unableToOpenTmpFile): +## %S will be replaced with the name of file that could not be opened +unableToOpenFile=No se puede abrir el archivo %S. +unableToOpenTmpFile=No se puede abrir el archivo temporal %S. Compruebe la configuración de su 'directorio temporal'. +unableToSaveTemplate=No es posible guardar su mensaje como plantilla. +unableToSaveDraft=No es posible guardar su mensaje como un borrador. +couldntOpenFccFolder=No se puede abrir la carpeta Enviados. Verifique que la configuración de su cuenta es correcta. +noSender=No se ha indicado remitente. Añada su dirección de correo en la configuración de la cuenta. +noRecipients=No se especificaron destinatarios. Introduzca un destinatario o grupo de noticias en el área de dirección. +errorWritingFile=Error al escribir el archivo temporal. + +## LOCALIZATION NOTE (errorSendingFromCommand): argument %s is the Outgoing server (SMTP) response +errorSendingFromCommand=Ocurrió un error mientras se enviaba el correo. El servidor de correo respondió: %s. Verifique que su dirección de correo electrónico es correcta en las preferencias de su cuenta y vuelva a intentarlo. + +## LOCALIZATION NOTE (errorSendingDataCommand): argument %s is the Outgoing server (SMTP) response +errorSendingDataCommand=Ocurrió un error en el servidor de salida (SMTP) al enviar el correo. El servidor respondió: %s. + +## LOCALIZATION NOTE (errorSendingMessage): argument %s is the Outgoing server (SMTP) response +errorSendingMessage=Ocurrió un error al enviar el correo. El servidor de correo respondió: %s. Compruebe el mensaje y vuelva a intentarlo. +postFailed=No se ha podido publicar el mensaje porque ha fallado la conexión al servidor de noticias. El servidor puede no estar disponible o está rechazando conexiones. Verifique que la configuración de su servidor de noticias es correcta y vuelva a intentarlo. +errorQueuedDeliveryFailed=Ocurrió un error al procesar sus mensajes no enviados. +sendFailed=Falló el envío del mensaje. + +## LOCALIZATION NOTE (sendFailedUnexpected): argument %X is a hex error code value +sendFailedUnexpected=Envío fallido debido al error inesperado %X. No hay ninguna descripción disponible. + +## LOCALIZATION NOTE (smtpSecurityIssue): argument %S is the Outgoing server (SMTP) response +smtpSecurityIssue=La configuración relacionada con %S debe corregirse. + +## LOCALIZATION NOTE (smtpServerError): argument %s is the Outgoing server (SMTP) response +smtpServerError=Ha sucedido un error al enviar el correo: error en el servidor de salida (SMTP). El servidor respondió: %s. +unableToSendLater=Lo sentimos, no hemos podido guardar su mensaje para enviarlo más tarde. + +## LOCALIZATION NOTE (communicationsError): argument %d is the error code +communicationsError=Ocurrió un error de comunicación: %d. Vuelva a intentarlo. +dontShowAlert=ESTO ES SOLO UNA RESERVA DE ESPACIO. NUNCA DEBERÍA VER ESTE TEXTO. + +couldNotGetUsersMailAddress2=Ha sucedido un error al enviar el correo: la dirección del remitente (De:) no es válida. Verifique que esta dirección de correo es correcta y vuelva a intentarlo. +couldNotGetSendersIdentity=Ha sucedido un error al enviar el correo: la identidad del remitente no es válida. Verifique la configuración de su identidad y vuelva a intentarlo. + +mimeMpartAttachmentError=Error en adjunto. +failedCopyOperation=El mensaje se envió con éxito, pero la copia a la carpeta Enviados falló. +nntpNoCrossPosting=Sólo puede enviar un mensaje a un servidor de noticias a la vez. +msgCancelling=Cancelando… +sendFailedButNntpOk=Su mensaje ha sido enviado al grupo de noticias pero no ha sido enviado al otro destinatario. +errorReadingFile=Error leyendo el archivo. +followupToSenderMessage=El autor de este mensaje ha pedido que las respuestas sean enviadas únicamente al autor. Si también quiere responder al grupo de noticias, añada una nueva fila en el area de direcciones, elija Grupo de la lista de cabeceras, e introduzca el nombre del grupo de noticias. + +## LOCALIZATION NOTE (errorAttachingFile): argument %S is the file name/URI of the object to be attached +errorAttachingFile=Ha habido un problema al adjuntar %S. Compruebe si tiene acceso al archivo. + +## LOCALIZATION NOTE (incorrectSmtpGreeting): argument %s is the Outgoing server (SMTP) greeting +incorrectSmtpGreeting=Ocurrió un error al enviar el correo: el servidor de correo envió un saludo incorrecto: %s. + +## LOCALIZATION NOTE (errorSendingRcptCommand): argument %1$S is the Outgoing server (SMTP) response, argument %2$S is the intended message recipient. +errorSendingRcptCommand=Ha ocurrido un error al enviar el mensaje. El servidor de correo respondió: \n%1$S.\nVerifique el destinatario "%2$S" y vuelva a intentarlo. + +## LOCALIZATION NOTE (startTlsFailed): argument %S is the Outgoing server (SMTP) +startTlsFailed=Ha ocurrido un error al enviar el mensaje: no es posible establecer un enlace seguro con el servidor de salida (SMTP) %S usando STARTTLS ya que no anuncia ese mecanismo. Desactive STARTTLS para ese servidor o contacte con su proveedor del servicio. + +## LOCALIZATION NOTE (smtpPasswordUndefined): argument %S is the Outgoing server (SMTP) account +smtpPasswordUndefined=Ha ocurrido un error al enviar el mensaje: no se ha podido obtener la contraseña para %S. El mensaje no se ha enviado. + +## LOCALIZATION NOTE (smtpSendNotAllowed): argument %s is the Outgoing server (SMTP) response +smtpSendNotAllowed=Ha ocurrido un error al enviar el mensaje. El servidor de correo ha respondido:\n%s.\nAsegúrese de que está usando la identidad correcta para el envío y el método de identificación usado es correcto. Verifique está autorizado a enviar a través de este servidor SMTP con sus credenciales actuales de la red que está usando ahora. + +## LOCALIZATION NOTE (smtpTempSizeExceeded): argument %s is the Outgoing server (SMTP) response +smtpTempSizeExceeded=El tamaño del mensaje que está intentando enviar excede un límite temporal de tamaño del servidor. El mensaje no se ha enviado; intente reducir el tamaño del mensaje o espere un rato y vuelva a intentarlo. El servidor respondió: %s. + +## LOCALIZATION NOTE (smtpClientid): argument %s is the Outgoing server (SMTP) response +smtpClientid=El servidor de salida (SMTP) ha detectado un error en la orden CLIENTID. No se ha enviado el mensaje. El servidor ha respondido: %s + +## LOCALIZATION NOTE (smtpClientidPermission): argument %s is the Outgoing server (SMTP) response +smtpClientidPermission=La respuesta del servidor de salida (SMTP) a la orden CLIENTID indica que su dispositivo no tiene permitido enviar correo. El servidor ha respondido: %s + +## LOCALIZATION NOTE (smtpPermSizeExceeded1): argument %d is the Outgoing server (SMTP) size limit +smtpPermSizeExceeded1=El tamaño del mensaje que está intentando enviar excede el límite global de tamaño (%d bytes) del servidor. El mensaje no se ha enviado; reduzca el tamaño del mensaje y vuelva a intentarlo. + +## LOCALIZATION NOTE (smtpPermSizeExceeded2): argument %s is the Outgoing server (SMTP) response +smtpPermSizeExceeded2=El tamaño del mensaje que está intentando enviar excede el límite global de tamaño del servidor. El mensaje no se ha enviado; reduzca el tamaño del mensaje y vuelva a intentarlo. El servidor respondió: %s. + +## LOCALIZATION NOTE (smtpSendFailedUnknownServer): argument %S is the Outgoing server (SMTP) +smtpSendFailedUnknownServer=Ha ocurrido un error al enviar el mensaje: el servidor de salida (SMTP) %S es desconocido. El servidor puede estar mal configurado. Verifique que la configuración de su servidor de salida (SMTP) es correcta y vuelva a intentarlo. + +## LOCALIZATION NOTE (smtpSendRequestRefused): argument %S is the Outgoing server (SMTP) +smtpSendRequestRefused=El mensaje no se ha podido enviar porque ha fallado la conexión al servidor de salida (SMTP) %S. El servidor puede no estar disponible o está rechazando conexiones SMTP. Verifique que los ajustes de su servidor de salida (SMTP) son correctos y vuelva a intentarlo. + +## LOCALIZATION NOTE (smtpSendInterrupted): argument %S is the Outgoing server (SMTP) +smtpSendInterrupted=El mensaje no se ha podido enviar porque la conexión al servidor de salida (SMTP) %S se perdió en mitad de la transacción. Vuelva a intentarlo. + +## LOCALIZATION NOTE (smtpSendTimeout): argument %S is the Outgoing server (SMTP) +smtpSendTimeout=El mensaje no se ha podido enviar porque ha caducado la conexión al servidor de salida (SMTP) %S. Vuelva a intentarlo. + +## LOCALIZATION NOTE (smtpSendFailedUnknownReason): argument %S is the Outgoing server (SMTP) +smtpSendFailedUnknownReason=El mensaje no se ha podido enviar usando el servidor de salida (SMTP) %S por una razón desconocida. Verifique que los ajustes de su servidor de salida (SMTP) son correctos y vuelva a intentarlo. + +# LOCALIZATION NOTE (smtpHintAuthEncryptToPlainNoSsl): %S is the server hostname +smtpHintAuthEncryptToPlainNoSsl=El servidor de salida (SMTP) %S no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)' a 'Contraseña, transmitida de forma insegura'. Si antes funcionaba pero ya no, puede que se le haya sustraído su contraseña. + +# LOCALIZATION NOTE (smtpHintAuthEncryptToPlainSsl): %S is the server hostname +smtpHintAuthEncryptToPlainSsl=El servidor de salida (SMTP) %S no parece admitir contraseñas cifradas. Si acaba de configurar la cuenta, pruebe a cambiar el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)' a 'Contraseña normal'. + +# LOCALIZATION NOTE (smtpHintAuthPlainToEncrypt): %S is the server hostname +smtpHintAuthPlainToEncrypt=El servidor de salida (SMTP) %S no admite contraseñas no cifradas. Pruebe a cambiar el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)' a 'Contraseña cifrada'. + +# LOCALIZATION NOTE (smtpAuthFailure): %S is the server hostname +smtpAuthFailure=No se puede identificar al servidor de salida (SMTP) %S. Compruebe la contraseña y verifique el 'Método de identificación' en 'Configuración de cuentas | Servidor de salida (SMTP)'. + +# LOCALIZATION NOTE (smtpAuthGssapi): %S is the server hostname +smtpAuthGssapi=El tique Kerberos/GSSAPI no ha sido aceptado por el servidor de salida (SMTP) %S. Compruebe que ha iniciado sesión en el dominio Kerberos/GSSAPI. + +# LOCALIZATION NOTE (smtpAuthMechNotSupported): %S is the server hostname +smtpAuthMechNotSupported=El servidor de salida (SMTP) %S no admite el mecanismo de identificación seleccionado. Cambie el 'Método de identificación' en la 'Configuración de cuentas | Servidor de salida (SMTP)'. + +# LOCALIZATION NOTE (errorIllegalLocalPart2): %s is an email address with an illegal localpart +errorIllegalLocalPart2=Hay caracteres no-ASCII en la parte local de la dirección de destino %s y su servidor no admite SMTPUTF8. Cambie esta dirección y vuelva a intentarlo. + +## Strings used for the save message dialog shown when the user closes a message compose window +saveDlogTitle=Guardar mensaje + +## LOCALIZATION NOTE (saveDlogMessages3): Do not translate the words %1$S and \n. +## %1$S is replaced by the folder name configured for saving drafts (typically the "Drafts" folder). +## Translate "Write" to match the translation of item "windowTitleWrite" below. +saveDlogMessages3=¿Guardar este mensaje en su carpeta de borradores (%1$S) y cerrar la ventana de redacción? +discardButtonLabel=&Descartar cambios + +## generics string +defaultSubject=(sin asunto) +chooseFileToAttach=Adjuntar archivo(s) +genericFailureExplanation=Verifique que la configuración de su cuenta es correcta y vuelva a intentarlo. + +## LOCALIZATION NOTE (undisclosedRecipients): this string must use only US_ASCII characters +undisclosedRecipients=destinatarios-no-revelados + +# LOCALIZATION NOTE (chooseFileToAttachViaCloud): %1$S is the cloud +# provider to save the file to. +chooseFileToAttachViaCloud=Adjuntar archivo(s) a través de %1$S + +## Window titles +# LOCALIZATION NOTE (windowTitleWrite): +# %1$S is the message subject. +# %2$S is the application name. +# Example: Write: Re: Invitation - Thunderbird +windowTitleWrite=Escribir: %1$S - %2$S +# LOCALIZATION NOTE (windowTitlePrintPreview): +# %1$S is the message subject. +# %2$S is the application name. +# Example: Print Preview: Re: Invitation - Thunderbird +windowTitlePrintPreview=Vista preliminar: %1$S - %2$S + +## From field +msgIdentityPlaceholder=Introduzca la dirección Desde personalizada que quiere usar en lugar de %S +customizeFromAddressTitle=Personalizar dirección De +customizeFromAddressWarning=Si su proveedor de correo lo admite, Personalizar dirección De le permite hacer una alteración menor puntual a su dirección de remite sin tener que crear una nueva identidad en la configuración de cuentas. Por ejemplo, si su dirección de remite es Juan Pérez puede que quiera cambiarlo a Juan Pếrez o Juan . +customizeFromAddressIgnore=No volver a avisarme de nuevo + +## Strings used by the empty subject dialog +subjectEmptyTitle=Recordatorio de asunto +subjectEmptyMessage=Su mensaje no tiene asunto. +sendWithEmptySubjectButton=&Enviar sin asunto +cancelSendingButton=&Cancelar envío + +## Strings used by the dialog that informs about the lack of newsgroup support. +noNewsgroupSupportTitle=Grupos de noticias no admitidos +recipientDlogMessage=Esta cuenta sólo soporta destinatarios de correo. Continuar ignorará los grupos de noticias. + +## Strings used by the alert that tells the user that an e-mail address is invalid. +addressInvalidTitle=Dirección de destinatario no válida +addressInvalid=%1$S no es una dirección de correo electrónico válida porque no tiene la forma usuario@dominio. Debe corregirse antes de enviar el correo. + +## String used by the dialog that asks the user to attach a web page +attachPageDlogTitle=Especifique qué dirección desea adjuntar +attachPageDlogMessage=Página web (URL): + +## String used for attachment pretty name, when the attachment is a message +messageAttachmentSafeName=Mensaje adjunto + +## String used for attachment pretty name, when the attachment is a message part +partAttachmentSafeName=Parte del mensaje adjunto + +# LOCALIZATION NOTE (attachmentBucketAttachFilesTooltip): +# This tooltip should be same as attachFile.label in messengercompose.dtd, +# but without ellipsis (…). +attachmentBucketAttachFilesTooltip=Adjuntar archivo(s) +attachmentBucketClearSelectionTooltip=Limpiar selección +attachmentBucketHeaderShowTooltip=Mostrar el panel de adjuntos +attachmentBucketHeaderMinimizeTooltip=Minimizar panel de adjuntos +attachmentBucketHeaderRestoreTooltip=Restaurar panel de adjuntos + +## String used by the Initialization Error dialog +initErrorDlogTitle=Redacción de mensaje +initErrorDlgMessage=Ha sucedido un error al crear una ventana de redacción de mensajes. Vuelva a intentarlo. + +## String used if a file to attach does not exist when passed as +## a command line argument +errorFileAttachTitle=Anexado de archivo + +## LOCALIZATION NOTE (errorFileAttachMessage): %1$S will be replaced by the non-existent file name. +errorFileAttachMessage=El archivo %1$S no existe por lo que no ha podido adjuntarse al mensaje. + +## String used if a file to serve as message body does not exist or cannot be loaded when passed +## as a command line argument +errorFileMessageTitle=Archivo de mensajes + +## LOCALIZATION NOTE (errorFileMessageMessage): %1$S will be replaced by the non-existent file name. +errorFileMessageMessage=El archivo %1$S no existe y no se ha podido usar como contenido del mensaje. + +## LOCALIZATION NOTE (errorLoadFileMessageMessage): %1$S will be replaced by the name of the file that can't be loaded. +errorLoadFileMessageMessage=No se ha podido cargar el archivo %1$S como contenido del mensaje. + +## Strings used by the Save as Draft/Template dialog +SaveDialogTitle=Guardar mensaje + +## LOCALIZATION NOTE (SaveDialogMsg): %1$S is the folder name, %2$S is the host name +SaveDialogMsg=Su mensaje se ha guardado en la carpeta %1$S en %2$S. +CheckMsg=No volver a mostrarme esta ventana de diálogo. + +## Strings used by the prompt when Quitting while in progress +quitComposeWindowTitle=Enviando mensaje + +## LOCALIZATION NOTE (quitComposeWindowMessage2): don't translate \n +quitComposeWindowMessage2=%1$S está actualmente enviando un mensaje.\n¿Quiere salir ahora, o esperar hasta que el mensaje haya sido enviado antes de salir? +quitComposeWindowQuitButtonLabel2=&Salir +quitComposeWindowWaitButtonLabel2=&Esperar +quitComposeWindowSaveTitle=Guardando mensaje + +## LOCALIZATION NOTE (quitComposeWindowSaveMessage): don't translate \n +quitComposeWindowSaveMessage=%1$S está actualmente guardando un mensaje.\n¿Quiere salir ahora, o esperar hasta que el mensaje haya sido guardado antes de salir? + +## Strings used by the prompt for Ctrl-Enter check before sending message +sendMessageCheckWindowTitle=Enviar mensaje +sendMessageCheckLabel=¿Seguro que está preparado para mandar este mensaje? +sendMessageCheckSendButtonLabel=Enviar +assemblingMessageDone=Ensamblando el mensaje… Listo +assemblingMessage=Ensamblando el mensaje… +smtpDeliveringMail=Enviando correo… +smtpMailSent=Correo enviado con éxito +assemblingMailInformation=Ensamblando la información de correo… + +## LOCALIZATION NOTE (gatheringAttachment): argument %S is the file name/URI of attachment +gatheringAttachment=Adjuntando %S… +creatingMailMessage=Creando mensaje de correo… + +## LOCALIZATION NOTE (copyMessageStart): argument %S is the folder name +copyMessageStart=Copiando el mensaje a la carpeta %S… +copyMessageComplete=Copia completada. +copyMessageFailed=Falló la copia. +filterMessageComplete=Filtro completo. +filterMessageFailed=Filtro fallido. + +## LOCALIZATION NOTE (largeMessageSendWarning): +## Do not translate %S. It is the size of the message in user-friendly notation. +largeMessageSendWarning=¡Advertencia! Está a punto de enviar un mensaje de tamaño %S. ¿Está seguro de que quiere hacerlo? +sendingMessage=Enviando el mensaje… +sendMessageErrorTitle=Error de envío de mensaje +postingMessage=Publicando el mensaje… +sendLaterErrorTitle=Error de envío posterior +saveDraftErrorTitle=Error guardando el borrador +saveTemplateErrorTitle=Error guardando la plantilla + +## LOCALIZATION NOTE (failureOnObjectEmbeddingWhileSaving): argument %.200S is the file name/URI of object to be embedded +failureOnObjectEmbeddingWhileSaving=Hubo un problema al incluir el archivo %.200S en el mensaje. ¿Quiere seguir guardando el mensaje sin el archivo? + +## LOCALIZATION NOTE (failureOnObjectEmbeddingWhileSending): argument %.200S is the file name/URI of object to be embedded +failureOnObjectEmbeddingWhileSending=Hubo un problema al incluir el archivo %.200S en el mensaje. ¿Quiere continuar el envío del mensaje sin este archivo? +returnToComposeWindowQuestion=¿Quiere volver a la ventana de redacción? + +## reply header in composeMsg +## LOCALIZATION NOTE (mailnews.reply_header_authorwrotesingle): #1 is the author (name of the person replying to) +mailnews.reply_header_authorwrotesingle=#1 escribió: + +## LOCALIZATION NOTE (mailnews.reply_header_ondateauthorwrote): #1 is the author, #2 is the date, #3 is the time +mailnews.reply_header_ondateauthorwrote=El #2 a las #3, #1 escribió: + +## LOCALIZATION NOTE (mailnews.reply_header_authorwroteondate): #1 is the author, #2 is the date, #3 is the time +mailnews.reply_header_authorwroteondate=#1 escribió el #2 a las #3: + +## reply header in composeMsg +## user specified +mailnews.reply_header_originalmessage=-------- Mensaje original -------- + +## forwarded header in composeMsg +## user specified +mailnews.forward_header_originalmessage=-------- Mensaje reenviado -------- + +## Strings used by the rename attachment dialog +renameAttachmentTitle=Renombrar adjunto +renameAttachmentMessage=Nuevo nombre del adjunto: + +## Attachment Reminder +## LOCALIZATION NOTE (mail.compose.attachment_reminder_keywords): comma separated +## words that should trigger an attachment reminder. +mail.compose.attachment_reminder_keywords=adjunto,adjuntado,.doc,.pdf,.xls,.ppt,.rtf,.pps,currículum,CV,carta de presentación,envío + +remindLaterButton=Recordármelo más tarde +remindLaterButton.accesskey=R +disableAttachmentReminderButton=Desactivar recordatorio de adjuntos en el mensaje actual +attachmentReminderTitle=Recordatorio de adjuntos +attachmentReminderMsg=¿Ha olvidado añadir un adjunto? + +# LOCALIZATION NOTE (attachmentReminderKeywordsMsgs): Semi-colon list of plural forms. +# See: https://developer.mozilla.org/en/Localization_and_Plurals +# #1 number of keywords +attachmentReminderKeywordsMsgs=Encontrada una palabra clave de adjuntos:;Encontradas #1 palabras clave de adjuntos: +attachmentReminderOptionsMsg=Las palabras recordatorios de adjuntos se pueden configurar en sus preferencias +attachmentReminderYesIForgot=¡Uups, sí, se me ha olvidado! +attachmentReminderFalseAlarm=No, enviar ahora + +# Strings used by the Filelink offer notification bar. +learnMore.label=Saber más… +learnMore.accesskey=m + +# LOCALIZATION NOTE (bigFileDescription): Semi-colon list of plural forms. +# See: https://developer.mozilla.org/en/Localization_and_Plurals +# #1 number of big attached files +bigFileDescription=Este archivo es grande. Podría ser mejor usar Filelink.;Estos archivos son grandes. Podría ser mejor usar Filelink. +bigFileShare.label=Enlazar +bigFileShare.accesskey=E +bigFileAttach.label=Ignorar +bigFileAttach.accesskey=I +bigFileChooseAccount.title=Elija una cuenta +bigFileChooseAccount.text=Elija una cuenta en la nube a la que subir el adjunto +bigFileHideNotification.title=No subir mis archivos +bigFileHideNotification.text=No se le avisará si adjunta más archivos grandes a este mensaje. +bigFileHideNotification.check=No volver a avisarme. + +# LOCALIZATION NOTE(cloudFileUploadingTooltip): Do not translate the string +# %S. %S is the display name for the cloud account the attachment is being +# uploaded to. +cloudFileUploadingTooltip=Subiendo a %S… + +# LOCALIZATION NOTE(cloudFileUploadedTooltip): Do not translate the string +# %S. %S is the display name for the cloud account the attachment was uploaded +# to. +cloudFileUploadedTooltip=Subido a %S +cloudFileUploadingNotification=Su archivo está siendo enlazado. Aparecerá en el cuerpo del mensaje cuando esté completo.;Sus archivos están siendo enlazados. Aparecerán en el cuerpo del mensaje cuando estén completos. +cloudFileUploadingCancel.label=Cancelar +cloudFileUploadingCancel.accesskey=C +cloudFilePrivacyNotification=Enlazado completado. Tenga en cuenta que los adjuntos enlazados pueden ser accesibles a las personas que puedan ver o adivinar los enlaces. + +## LOCALIZATION NOTE(smtpEnterPasswordPrompt): Do not translate the +## word %S. Place the word %S where the host name should appear. +smtpEnterPasswordPrompt=Introduzca su contraseña para %S: + +## LOCALIZATION NOTE(smtpEnterPasswordPromptWithUsername): Do not translate the +## words %1$S and %2$S. Place the word %1$S where the host name should appear, +## and %2$S where the user name should appear. +smtpEnterPasswordPromptWithUsername=Introduzca la contraseña para %2$S en %1$S: +## LOCALIZATION NOTE(smtpEnterPasswordPromptTitleWithHostname): Do not translate the +## word %1$S. Place the word %1$S where the server host name should appear. +smtpEnterPasswordPromptTitleWithHostname=Contraseña necesaria para el servidor saliente (SMTP) %1$S + +# LOCALIZATION NOTE (removeAttachmentMsgs): Semi-colon list of plural forms. +# See: https://developer.mozilla.org/en/Localization_and_Plurals +removeAttachmentMsgs=Eliminar adjunto;Eliminar adjuntos + +## LOCALIZATION NOTE(promptToSaveSentLocally2): Do not translate the strings %1$S, %2$S, %3$S and \n. +## %2$S will be replaced with the account name. $1$S will be replaced by the folder name +## configured to contain saved sent messages (typically the "Sent" folder). +## %3$S will be replaced with the local folders account name (typically "Local Folders"). +## Translate "Write" to match the translation of item "windowTitleWrite" above. +promptToSaveSentLocally2=Su mensaje se ha enviado pero no se ha copiado a su carpeta de mensajes enviados (%1$S) debido a errores de red o acceso a archivos.\nPuede reintentar o guardar el mensaje en modo local a %3$S/%1$S-%2$S. +errorFilteringMsg=Su mensaje ha sido enviado y guardado, pero ha sucedido un error al aplicarle los filtros de mensajes. +errorCloudFileAuth.title=Error de identificación + +## LOCALIZATION NOTE(promptToSaveDraftLocally2): Do not translate the strings %1$S, %2$S, %3$S and \n. +## %2$S will be replaced with the account name. $1$S will be replaced by the folder name +## configured to contain saved draft messages (typically the "Drafts" folder). +## %3$S will be replaced with the local folders account name (typically "Local Folders"). +promptToSaveDraftLocally2=Su borrador de mensaje no se ha copiado a su carpeta de borradores (%1$S) debido a errores de red o acceso a archivos.\nPuede reintentar o guardar el borrador en modo local a %3$S/%1$S-%2$S. +buttonLabelRetry2=&Reintentar + +## LOCALIZATION NOTE(promptToSaveTemplateLocally2): Do not translate the strings %1$S, %2$S, %3$S and \n. +## %2$S will be replaced with the account name. $1$S will be replaced by the folder name +## configured to contain saved templates (typically the "Templates" folder). +## %3$S will be replaced with the local folders account name (typically "Local Folders"). +promptToSaveTemplateLocally2=Su plantilla de mensaje no se ha copiado a su carpeta de plantillas (%1$S) debido a errores de red o acceso a archivos.\nPuede reintentar o guardar la plantilla en modo local a %3$S/%1$S-%2$S. + +## LOCALIZATION NOTE(saveToLocalFoldersFailed): Message appears after normal +## save fails (e.g., to Sent) and save to Local Folders also fails. This could +## occur if network is down and filesystem problems are present such as disk +## full, permission issues or hardware failure. +saveToLocalFoldersFailed=No se puede guardar su mensaje en las carpetas locales. Posiblemente no disponga de espacio de almacenamiento suficiente. + +## LOCALIZATION NOTE(errorCloudFileAuth.message): +## %1$S is the name of the online storage service against which the authentication failed. +errorCloudFileAuth.message=No se puede iniciar sesión en %1$S. +errorCloudFileUpload.title=Error de subida + +## LOCALIZATION NOTE(errorCloudFileUpload.message): +## %1$S is the name of the online storage service against which the uploading failed. +## %2$S is the name of the file that failed to upload. +errorCloudFileUpload.message=No se puede subir %2$S a %1$S. +errorCloudFileQuota.title=Error de cuota + +## LOCALIZATION NOTE(errorCloudFileQuota.message): +## %1$S is the name of the online storage service being uploaded to. +## %2$S is the name of the file that could not be uploaded due to exceeding the storage limit. +errorCloudFileQuota.message=Subir %2$S a %1$S excedería su cuota de espacio. +errorCloudFileNameLimit.title=Error en el nombre del archivo + +## LOCALIZATION NOTE(errorCloudFileNameLimit.message): +## %1$S is the name of the online storage service being uploaded to. +## %2$S is the name of the file that could not be uploaded due to the excess file name length +errorCloudFileNameLimit.message=%2$S contiene más de 120 caracteres en su nombre, lo que supera la longitud máxima de nombre de archivo para %1$S. Renombre el archivo para que su nombre tenga 120 caracteres o menos y súbalo de nuevo. +errorCloudFileLimit.title=Error en el tamaño del archivo + +## LOCALIZATION NOTE(errorCloudFileLimit.message): +## %1$S is the name of the online storage service being uploaded to. +## %2$S is the name of the file that could not be uploaded due to size restrictions. +errorCloudFileLimit.message=%2$S excede el tamaño máximo para %1$S. +errorCloudFileOther.title=Error desconocido\u0020 + +## LOCALIZATION NOTE(errorCloudFileOther.message): +## %1$S is the name of the online storage service that cannot be communicated with. +errorCloudFileOther.message=Ha sucedido un error desconocido durante la comunicación con %1$S. +errorCloudFileDeletion.title=Error de borrado + +## LOCALIZATION NOTE(errorCloudFileDeletion.message): +## %1$S is the name of the online storage service that the file is to be deleted from. +## %2$S is the name of the file that failed to be deleted. +errorCloudFileDeletion.message=Ha sucedido un problema al eliminar %2$S de %1$S. +errorCloudFileUpgrade.label=Actualizar + +## LOCALIZATION NOTE(cloudAttachmentCountHeader): A line of text describing how +## many uploaded files have been appended to this message. Emphasis should be +## on sharing as opposed to attaching. This item is used as a header to a list, +## hence the colon. This header is only displayed in HTML emails. +## Using PluralForm (so don't replace the #1). +cloudAttachmentCountHeader=He enlazado #1 archivo a este mensaje:;He enlazado #1 archivos a este mensaje: + +## LOCALIZATION NOTE(cloudAttachmentListItem): A line of text describing a cloud +## attachment to be inserted into the message body. Do not translate the words +## %1$S, %2$S, %3$S, or %4$S. %1$S is the attachment name, %2$S is its size, +## %3$S is the name of the cloud storage service, and %4$S is the link to the +## attachment. +cloudAttachmentListItem=* %1$S (%2$S) alojado en %3$S: %4$S + +## LOCALIZATION NOTE(stopShowingUploadingNotification): This string is used in the Filelink +## upload notification bar to allow the user to dismiss the notification permanently. +stopShowingUploadingNotification.accesskey=N +stopShowingUploadingNotification.label=No mostrar esto de nuevo +replaceButton.label=Reemplazar… +replaceButton.accesskey=R +replaceButton.tooltip=Mostrar el diálogo Buscar y reemplazar + +## LOCALIZATION NOTE(blockedAllowResource): %S is the URL to load. +blockedAllowResource=Desbloquear %S +## LOCALIZATION NOTE (blockedContentMessage): Semi-colon list of plural forms. +## See: https://developer.mozilla.org/en/docs/Localization_and_Plurals +## %S will be replaced by brandShortName. +## Files must be unblocked individually, therefore the plural form reads: +## Unblocking a file (one of several) will include it (that one file) in your sent message. +## In other words: +## Unblocking one/several file(s) will include it/them in your message. +blockedContentMessage=%S ha bloqueado la carga de un archivo en este mensaje. Desbloquear el archivo lo incluirá en su mensaje enviado.;%S ha bloqueado la carga de algunos archivos en este mensaje. Desbloquear un archivo lo incluirá en su mensaje enviado. + +blockedContentPrefLabel=Opciones +blockedContentPrefAccesskey=O + +blockedContentPrefLabelUnix=Preferencias +blockedContentPrefAccesskeyUnix=P + +## Recipient pills fields. +## LOCALIZATION NOTE(confirmRemoveRecipientRowTitle2): %S will be replaced with the field name. +confirmRemoveRecipientRowTitle2=Eliminar direcciones %S +## LOCALIZATION NOTE(confirmRemoveRecipientRowBody2): %S will be replaced with the field name. +confirmRemoveRecipientRowBody2=¿Está seguro de que quiere eliminar las direcciones %S? +confirmRemoveRecipientRowButton=Eliminar + +## LOCALIZATION NOTE headersSpaceStyle is for aligning label of a newly create recipient row. +## It should be larger than the largest Header label and identical to &headersSpace2.style; +headersSpaceStyle=width: 8em diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:37:33.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:52:23.000000000 +0000 @@ -2,13 +2,16 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + + + @@ -18,6 +21,7 @@ + @@ -46,6 +50,7 @@ + @@ -85,15 +90,23 @@ + + + + @@ -112,9 +125,11 @@ + + @@ -126,6 +141,7 @@ + @@ -162,6 +178,7 @@ + @@ -174,12 +191,14 @@ + + @@ -187,19 +206,21 @@ + - - - + + + - + @@ -211,6 +232,7 @@ + @@ -229,6 +251,7 @@ + @@ -245,6 +268,7 @@ + @@ -271,19 +295,26 @@ - + + + + + + diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messenger.dtd thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messenger.dtd --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messenger.dtd 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messenger.dtd 2022-04-15 07:52:23.000000000 +0000 @@ -5,6 +5,7 @@ + @@ -15,6 +16,10 @@ + @@ -31,12 +36,12 @@ - - - - - - + + + + + + @@ -85,6 +90,7 @@ + @@ -125,6 +131,7 @@ + @@ -162,6 +169,7 @@ + @@ -260,6 +268,7 @@ + @@ -279,6 +288,7 @@ + @@ -320,6 +330,7 @@ + @@ -361,7 +372,7 @@ - + @@ -440,8 +451,10 @@ + + @@ -454,10 +467,10 @@ - - - - + + + + @@ -477,12 +490,19 @@ + + + + @@ -494,6 +514,7 @@ + @@ -527,6 +548,7 @@ + @@ -556,9 +578,11 @@ + + @@ -566,6 +590,7 @@ + @@ -573,6 +598,7 @@ + @@ -580,16 +606,19 @@ + + + @@ -631,11 +660,14 @@ + + + @@ -644,6 +676,7 @@ + @@ -665,9 +698,9 @@ - + @@ -690,12 +723,16 @@ - + + @@ -740,6 +777,10 @@ + @@ -748,11 +789,47 @@ + + + + + @@ -763,12 +840,35 @@ - + + + + + @@ -794,9 +894,11 @@ + + @@ -816,28 +918,33 @@ + + - - - - - - - - + + + + + + + + + - - + + - - - + + + + - + + diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messenger.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messenger.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/messenger.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/messenger.properties 2022-04-15 07:52:23.000000000 +0000 @@ -5,203 +5,284 @@ # The following are used by the messenger application # -statusMessage = %1$S: %2$S - -removeAccount = Eliminar cuenta… -newFolderMenuItem = Carpeta… -newSubfolderMenuItem = Subcarpeta… -newFolder = Nueva carpeta… -newSubfolder = Nueva subcarpeta… -markFolderRead = Marcar carpeta como leída;Marcar carpetas como leídas -markNewsgroupRead = Marcar grupo de noticias como leído;Marcar grupos de noticias cmo leídos -folderProperties = Propiedades de carpeta -newTag = Nueva etiqueta… -getNextNewsMessages = Obtener #1 mensaje de noticias siguiente;Obtener #1 mensajes de noticias siguientes -advanceNextPrompt = ¿Ir al siguiente mensaje no leído en %S? -titleNewsPreHost = en -replyToSender = Responder al remitente -reply = Responder -EMLFiles = Archivos de correo (*.eml) -OpenEMLFiles = Abrir mensaje -defaultSaveMessageAsFileName = message.eml -longMsgSubjectTruncator = ... -SaveMailAs = Guardar mensaje como -SaveAttachment = Salvar adjunto -SaveAllAttachments = Salvar todos los adjuntos -DetachAttachment = Separar adjunto -DetachAllAttachments = Separar todos los adjuntos -ChooseFolder = Escoger carpeta -MessageLoaded = Mensaje cargado… -PreviewTitle = %S - %S -saveAttachmentFailed = Imposible guardar el adjunto. Compruebe el nombre de su archivo y vuelva a intentarlo. -saveMessageFailed = Imposible guardar el mensaje. Compruebe el nombre del archivo y pruebe otra vez. -fileExists = %S ya existe. ¿Desea reemplazarlo? -failedToReadFile = No se ha podido leer el archivo: %1$S razón: %2$S - -downloadingNewsgroups = Descargando grupos de noticias para usar sin conexión -downloadingMail = Descargando el correo para uso sin conexión -sendingUnsent = Procesando mensajes no enviados - -folderExists = Ya existe una carpeta con ese nombre. Pruebe con un nombre diferente. -confirmDuplicateFolderRename = Ya existe una subcarpeta con el nombre '%1$S' en la carpeta '%2$S'. ¿Le gustaría mover esta carpeta usando el nombre nuevo '%3$S'? -folderCreationFailed = La carpeta no pudo crearse porque el nombre de la carpeta que ha especificado contiene un carácter no reconocido. Introduzca un nombre diferente y vuelva a intentarlo. - -compactingFolder = Compactando la carpeta %S… -compactingDone = Compactación terminada (aprox. %1$S recuperado). - -confirmFolderDeletionForFilter = Al eliminar la carpeta '%S' se desactivarán los filtros asociados. ¿Seguro que quiere eliminar la carpeta? -alertFilterChanged = Los filtros asociados con esta carpeta serán actualizados. -filterDisabled = La carpeta '%S' no se pudo encontrar, por lo que los filtros asociados con esta carpeta serán desactivados. Compruebe que la carpeta existe, y que los filtros apuntan a una carpeta de destino válida. -filterFolderDeniedLocked = Los mensajes no pudieron ser filtrados a la carpeta '%S' porque hay otra operación en curso. -parsingFolderFailed = No se pudo abrir la carpeta %S porque ésta está en uso por alguna otra operación. Espere a que termine esa operación y seleccione esa carpeta de nuevo. -deletingMsgsFailed = No se pudieron eliminar mensajes en la carpeta %S porque ésta está en uso por alguna otra operación. Espere que esa operación concluya y vuelva a intentarlo. -alertFilterCheckbox = No volver a avisarme. -compactFolderDeniedLock = La carpeta '%S' no puede ser compactada porque hay otra operación en curso. Inténtelo más tarde. -compactFolderWriteFailed = La carpeta '%S' no se pudo compactar porque falló la escritura en la carpeta. Compruebe que tiene suficiente espacio en disco y privilegios de escritura en el directorio, y vuelva a intentarlo. -compactFolderInsufficientSpace = Algunas carpetas (p.e. '%S') no se pueden compactar porque no hay suficiente espacio libre en disco. Elimine algunos archivos y vuelva a intentarlo. -filterFolderHdrAddFailed = Los mensajes no se han podido filtrar a la carpeta '%S' porque no se pudo añadir un mensaje en ella. Verifique que la carpeta se está mostrando correctamente o intente repararla desde las propiedades de la carpeta. -filterFolderWriteFailed = Los mensajes no pudieron ser filtrados a la carpeta '%S' porque falló la escritura a esa carpeta. Compruebe que tiene suficiente espacio en disco y permiso de escritura en el directorio, e inténtelo de nuevo. -copyMsgWriteFailed = Los mensajes no han podido ser movidos o copiados a la carpeta '%S' porque falló la escritura en esa carpeta. Para conseguir más espacio, desde el menú Archivo, escoja primero Vaciar Papelera, y luego escoja Compactar carpetas, y vuelva a intentarlo. -cantMoveMsgWOBodyOffline = Cuando se encuentra en modo sin conexión, no puede mover o copiar mensajes que no hayan sido descargados para su uso desconectado. Desde la ventana de correo, abra el menú Archivo, escoja Sin conexión, luego desmarque Trabajar con conexión, y vuelva a intentarlo. -operationFailedFolderBusy = La operación ha fallado porque otra operación está usando la carpeta. Espere a que ésta termine e inténtelo de nuevo. -folderRenameFailed = No se pudo renombrar la carpeta. Tal vez la carpeta está siendo releída, o el nuevo nombre de la carpeta no es válido. -verboseFolderFormat = %1$S en %2$S -filterFolderTruncateFailed = Ha sucedido un error al truncar la bandeja de entrada tras filtrar un mensaje a la carpeta '%1$S'. Puede que necesite cerrar %2$S y eliminar INBOX.msf. - -mailboxTooLarge = La carpeta %S está llena, y no puede retener más mensajes. Para hacer sitio para más mensajes, borre cualquier correo antiguo o no deseado y compacte la carpeta. -outOfDiskSpace = No hay suficiente espacio en disco para descargar nuevos mensajes. Pruebe a borrar el correo antiguo, vaciar la papelera de reciclaje y compactar sus carpetas de correo, y luego vuelva a intentarlo. -errorGettingDB = No se puede abrir el archivo resumen de %S. Quizá hay un error en el disco, o la ruta completa es demasiado larga. -defaultServerTag = (Predeterminado) - -messageUnread = No leído -messageHasFlag = Con estrella -messageHasAttachment = Tiene adjunto -messageJunk = Correo no deseado -messageExpanded = Expandido -messageCollapsed = Contraído - -smtpServerList-NotSpecified = -smtpServer-ConnectionSecurityType-0 = Ninguna -smtpServer-ConnectionSecurityType-1 = STARTTLS, si está disponible -smtpServer-ConnectionSecurityType-2 = STARTTLS -smtpServer-ConnectionSecurityType-3 = SSL/TLS -smtpServers-confirmServerDeletionTitle = Eliminar servidor -smtpServers-confirmServerDeletion = ¿Seguro que desea eliminar el servidor: \n %S? - -authNo = Sin identificación -authOld = Contraseña, método original (inseguro) -authPasswordCleartextInsecurely = Contraseña, transmitida de manera insegura -authPasswordCleartextViaSSL = Contraseña normal -authPasswordEncrypted = Contraseña cifrada -authKerberos = Kerberos / GSSAPI -authExternal = Certificado TLS -authNTLM = NTLM -authOAuth2 = OAuth2 -authAnySecure = Cualquier método seguro (obsoleto) -authAny = Cualquier método (inseguro) - -oauth2WindowTitle = Introduzca las credenciales para %1$S en %2$S - -serverType-nntp = Servidor de noticias (NNTP) -serverType-pop3 = Servidor de correo POP -serverType-imap = Servidor de correo IMAP -serverType-none = Almacén de correo local - -sizeColumnTooltip2 = Ordenar por tamaño -sizeColumnHeader = Tamaño -linesColumnTooltip2 = Ordenar por líneas -linesColumnHeader = Líneas - -getMsgButtonTooltip = Recibir mensajes nuevos de %S -getMsgButtonTooltip.listSeparator = ,\u0020 - -documentDone = -documentLoading = Cargando mensaje… - -autosyncProgress = Sincronizando mensajes en %1$S desde %2$S… - -unreadMsgStatus = Sin leer: %S -selectedMsgStatus = Seleccionado: %S -totalMsgStatus = Total: %S +# LOCALIZATION NOTE(statusMessage): +# Do not translate the words %1$S and %2$S below. Place the word %1$S where the +# account name should appear and %2$S where the status message should appear. +# EXAMPLE: Jim's Account: Downloading messages... +statusMessage=%1$S: %2$S + +removeAccount=Eliminar cuenta… +newFolderMenuItem=Carpeta… +newSubfolderMenuItem=Subcarpeta… +newFolder=Nueva carpeta… +newSubfolder=Nueva subcarpeta… +markFolderRead=Marcar carpeta como leída;Marcar carpetas como leídas +markNewsgroupRead=Marcar grupo de noticias como leído;Marcar grupos de noticias cmo leídos +folderProperties=Propiedades de carpeta +newTag=Nueva etiqueta… +# LOCALIZATION NOTE (getNextNewsMessages): Semi-colon list of plural forms. +# #1 is the number of news messages to get. +getNextNewsMessages=Obtener #1 mensaje de noticias siguiente;Obtener #1 mensajes de noticias siguientes +advanceNextPrompt=¿Ir al siguiente mensaje no leído en %S? +titleNewsPreHost=en +replyToSender=Responder al remitente +reply=Responder +EMLFiles=Archivos de correo (*.eml) +OpenEMLFiles=Abrir mensaje +# LOCALIZATION NOTE(defaultSaveMessageAsFileName): Do not translate ".eml" +# in the line below. Also, the complete file name should be 8.3. +defaultSaveMessageAsFileName=message.eml +# LOCALIZATION NOTE(longMsgSubjectTruncator): A suffix string appended to the filename +# (created from message subject) if it needed to be truncated due to length. +longMsgSubjectTruncator=... +SaveMailAs=Guardar mensaje como +SaveAttachment=Salvar adjunto +SaveAllAttachments=Salvar todos los adjuntos +DetachAttachment=Separar adjunto +DetachAllAttachments=Separar todos los adjuntos +ChooseFolder=Escoger carpeta +MessageLoaded=Mensaje cargado… +PreviewTitle=%S - %S +saveAttachmentFailed=Imposible guardar el adjunto. Compruebe el nombre de su archivo y vuelva a intentarlo. +saveMessageFailed=Imposible guardar el mensaje. Compruebe el nombre del archivo y pruebe otra vez. +fileExists=%S ya existe. ¿Desea reemplazarlo? +# LOCALIZATION NOTE(failedToReadFile): %1$S is replaced by the file name, %2$S is replaced by the reason the file load failed. +failedToReadFile=No se ha podido leer el archivo: %1$S razón: %2$S + +downloadingNewsgroups=Descargando grupos de noticias para usar sin conexión +downloadingMail=Descargando el correo para uso sin conexión +sendingUnsent=Procesando mensajes no enviados + +folderExists=Ya existe una carpeta con ese nombre. Pruebe con un nombre diferente. +# LOCALIZATION NOTE(confirmDuplicateFolderRename): %1$S is name of folder being moved, %2$S is parent folder name, %3$S is proposed new folder name +confirmDuplicateFolderRename=Ya existe una subcarpeta con el nombre '%1$S' en la carpeta '%2$S'. ¿Le gustaría mover esta carpeta usando el nombre nuevo '%3$S'? +folderCreationFailed=La carpeta no pudo crearse porque el nombre de la carpeta que ha especificado contiene un carácter no reconocido. Introduzca un nombre diferente y vuelva a intentarlo. + +compactingFolder=Compactando la carpeta %S… +# LOCALIZATION NOTE(compactingDone): %1$S is the compaction gain. +compactingDone=Compactación terminada (aprox. %1$S recuperado). + +confirmFolderDeletionForFilter=Al eliminar la carpeta '%S' se desactivarán los filtros asociados. ¿Seguro que quiere eliminar la carpeta? +alertFilterChanged=Los filtros asociados con esta carpeta serán actualizados. +filterDisabled=La carpeta '%S' no se pudo encontrar, por lo que los filtros asociados con esta carpeta serán desactivados. Compruebe que la carpeta existe, y que los filtros apuntan a una carpeta de destino válida. +filterFolderDeniedLocked=Los mensajes no pudieron ser filtrados a la carpeta '%S' porque hay otra operación en curso. +parsingFolderFailed=No se pudo abrir la carpeta %S porque ésta está en uso por alguna otra operación. Espere a que termine esa operación y seleccione esa carpeta de nuevo. +deletingMsgsFailed=No se pudieron eliminar mensajes en la carpeta %S porque ésta está en uso por alguna otra operación. Espere que esa operación concluya y vuelva a intentarlo. +alertFilterCheckbox=No volver a avisarme. +compactFolderDeniedLock=La carpeta '%S' no puede ser compactada porque hay otra operación en curso. Inténtelo más tarde. +compactFolderWriteFailed=La carpeta '%S' no se pudo compactar porque falló la escritura en la carpeta. Compruebe que tiene suficiente espacio en disco y privilegios de escritura en el directorio, y vuelva a intentarlo. +compactFolderInsufficientSpace=Algunas carpetas (p.e. '%S') no se pueden compactar porque no hay suficiente espacio libre en disco. Elimine algunos archivos y vuelva a intentarlo. +filterFolderHdrAddFailed=Los mensajes no se han podido filtrar a la carpeta '%S' porque no se pudo añadir un mensaje en ella. Verifique que la carpeta se está mostrando correctamente o intente repararla desde las propiedades de la carpeta. +filterFolderWriteFailed=Los mensajes no pudieron ser filtrados a la carpeta '%S' porque falló la escritura a esa carpeta. Compruebe que tiene suficiente espacio en disco y permiso de escritura en el directorio, e inténtelo de nuevo. +copyMsgWriteFailed=Los mensajes no han podido ser movidos o copiados a la carpeta '%S' porque falló la escritura en esa carpeta. Para conseguir más espacio, desde el menú Archivo, escoja primero Vaciar Papelera, y luego escoja Compactar carpetas, y vuelva a intentarlo. +cantMoveMsgWOBodyOffline=Cuando se encuentra en modo sin conexión, no puede mover o copiar mensajes que no hayan sido descargados para su uso desconectado. Desde la ventana de correo, abra el menú Archivo, escoja Sin conexión, luego desmarque Trabajar con conexión, y vuelva a intentarlo. +operationFailedFolderBusy=La operación ha fallado porque otra operación está usando la carpeta. Espere a que ésta termine e inténtelo de nuevo. +folderRenameFailed=No se pudo renombrar la carpeta. Tal vez la carpeta está siendo releída, o el nuevo nombre de la carpeta no es válido. +# LOCALIZATION NOTE(verboseFolderFormat): %1$S is folder name, %2$S is server name +verboseFolderFormat=%1$S en %2$S +# LOCALIZATION NOTE(filterFolderTruncateFailed): %1$S is replaced by the folder name, %2$S is replaced by the brandShortName +filterFolderTruncateFailed=Ha sucedido un error al truncar la bandeja de entrada tras filtrar un mensaje a la carpeta '%1$S'. Puede que necesite cerrar %2$S y eliminar INBOX.msf. + +mailboxTooLarge=La carpeta %S está llena, y no puede retener más mensajes. Para hacer sitio para más mensajes, borre cualquier correo antiguo o no deseado y compacte la carpeta. +outOfDiskSpace=No hay suficiente espacio en disco para descargar nuevos mensajes. Pruebe a borrar el correo antiguo, vaciar la papelera de reciclaje y compactar sus carpetas de correo, y luego vuelva a intentarlo. +errorGettingDB=No se puede abrir el archivo resumen de %S. Quizá hay un error en el disco, o la ruta completa es demasiado larga. +defaultServerTag=(Predeterminado) + +# Used in message database list view to provide a text value for graphic based cells. +messageUnread=No leído +messageHasFlag=Con estrella +messageHasAttachment=Tiene adjunto +messageJunk=Correo no deseado +messageExpanded=Expandido +messageCollapsed=Contraído + +# Used in the SMTP Account Settings panel when a server value has no properties +smtpServerList-NotSpecified= +smtpServer-ConnectionSecurityType-0=Ninguna +smtpServer-ConnectionSecurityType-1=STARTTLS, si está disponible +smtpServer-ConnectionSecurityType-2=STARTTLS +smtpServer-ConnectionSecurityType-3=SSL/TLS +smtpServers-confirmServerDeletionTitle=Eliminar servidor +smtpServers-confirmServerDeletion=¿Seguro que desea eliminar el servidor: \n %S? + +# Account Settings - Both Incoming and SMTP server +authNo=Sin identificación +authOld=Contraseña, método original (inseguro) +authPasswordCleartextInsecurely=Contraseña, transmitida de manera insegura +authPasswordCleartextViaSSL=Contraseña normal +authPasswordEncrypted=Contraseña cifrada +authKerberos=Kerberos / GSSAPI +authExternal=Certificado TLS +authNTLM=NTLM +authOAuth2=OAuth2 +authAnySecure=Cualquier método seguro (obsoleto) +authAny=Cualquier método (inseguro) + +# OAuth2 window title +# LOCALIZATION NOTE(oauth2WindowTitle): +# %1$S is the username (or full email address) used for authentication. +# %2$S is the hostname of the account being authenticated. +oauth2WindowTitle=Introduzca las credenciales para %1$S en %2$S + +# LOCALIZATION NOTE(serverType-nntp): Do not translate "NNTP" in the line below +serverType-nntp=Servidor de noticias (NNTP) +# LOCALIZATION NOTE(serverType-pop3): Do not translate "POP" in the line below +serverType-pop3=Servidor de correo POP +# LOCALIZATION NOTE(serverType-imap): Do not translate "IMAP" in the line below +serverType-imap=Servidor de correo IMAP +serverType-none=Almacén de correo local + +sizeColumnTooltip2=Ordenar por tamaño +sizeColumnHeader=Tamaño +linesColumnTooltip2=Ordenar por líneas +linesColumnHeader=Líneas + +# LOCALIZATION NOTE (getMsgButtonTooltip): Do not translate the word "%S" below. +# Place the word "%S" in your translation where the name of the comma separated accounts should appear. +getMsgButtonTooltip=Recibir mensajes nuevos de %S +# Used to separate email addresses in a list. Note the trailing space ', ' +getMsgButtonTooltip.listSeparator=,\u0020 + +# status feedback stuff +documentDone= +documentLoading=Cargando mensaje… + +# LOCALIZATION NOTE (autosyncProgress): Do not translate the word "%1$S" or "%2$S" below. +# Place the word %1$S in your translation where the name of the comma separated folders should appear. +# Place the word %2$S in your translation where the name of the comma separated accounts should appear. +autosyncProgress=Sincronizando mensajes en %1$S desde %2$S… + +unreadMsgStatus=Sin leer: %S +selectedMsgStatus=Seleccionado: %S +totalMsgStatus=Total: %S # localized folder names -localFolders = Carpetas locales - -inboxFolderName = Bandeja de entrada -trashFolderName = Papelera -sentFolderName = Enviados -draftsFolderName = Borradores -templatesFolderName = Plantillas -outboxFolderName = Bandeja de salida -junkFolderName = Correo no deseado -archivesFolderName = Archivos - -priorityLowest = La más baja -priorityLow = Baja -priorityNormal = Normal -priorityHigh = Alta -priorityHighest = La más alta - -today = Hoy -yesterday = Ayer -lastWeek = Última semana -last7Days = Los últimos 7 días -twoWeeksAgo = Hace dos semanas -last14Days = Los últimos 14 días -older = Más antiguo -futureDate = Futuro - -untaggedMessages = Mensajes no etiquetados - -messagesWithNoStatus = Sin estado - -noPriority = Sin prioridad - -noAttachments = Sin adjuntos -attachments = Adjuntos - -notFlagged = Sin estrella -groupFlagged = Con estrella - -mailnews.tags.remove = Eliminar todas las etiquetas -mailnews.labels.description.1 = Importante -mailnews.labels.description.2 = Trabajo -mailnews.labels.description.3 = Personal -mailnews.labels.description.4 = Por hacer -mailnews.labels.description.5 = Más tarde - -mailnews.tags.format = %1$S %2$S +localFolders=Carpetas locales -replied = Respondido -forwarded = Reenviado -new = Nuevo -read = Leído -flagged = Con estrella - -junk = No deseado - -junkScoreOriginPlugin = Plugin -junkScoreOriginFilter = Filtro -junkScoreOriginWhitelist = Lista blanca -junkScoreOriginUser = Usuario -junkScoreOriginImapFlag = Indicador IMAP - -hasAttachments = Tiene adjuntos - -tag = Etiquetas - -andOthers = y otros - -mail.addr_book.displayName.lastnamefirst = false - -mail.addr_book.show_phonetic_fields = false - -mailnews.search_date_format = 0 -mailnews.search_date_separator = -mailnews.search_date_leading_zeros = true +# LOCALIZATION NOTE (inboxFolderName): OK to translate all foldernames, bugzilla #57440 & bugzilla #23625 fixed +inboxFolderName=Bandeja de entrada +trashFolderName=Papelera +sentFolderName=Enviados +draftsFolderName=Borradores +templatesFolderName=Plantillas +outboxFolderName=Bandeja de salida +junkFolderName=Correo no deseado +archivesFolderName=Archivos + +# "Normal" priority is often blank, +# depending on the consumers of these strings +priorityLowest=La más baja +priorityLow=Baja +priorityNormal=Normal +priorityHigh=Alta +priorityHighest=La más alta + +#Group by date thread pane titles +today=Hoy +yesterday=Ayer +lastWeek=Última semana +last7Days=Los últimos 7 días +twoWeeksAgo=Hace dos semanas +last14Days=Los últimos 14 días +older=Más antiguo +futureDate=Futuro + +#Grouped By Tags +untaggedMessages=Mensajes no etiquetados + +# Grouped by status +messagesWithNoStatus=Sin estado + +#Grouped by priority +noPriority=Sin prioridad + +#Grouped by has attachments +noAttachments=Sin adjuntos +attachments=Adjuntos + +#Grouped by starred +notFlagged=Sin estrella +groupFlagged=Con estrella + +# defaults descriptions for tag prefs listed in mailnews.js +# (we keep the .labels. names for backwards compatibility) +mailnews.tags.remove=Eliminar todas las etiquetas +mailnews.labels.description.1=Importante +mailnews.labels.description.2=Trabajo +mailnews.labels.description.3=Personal +mailnews.labels.description.4=Por hacer +mailnews.labels.description.5=Más tarde + +# Format definition tag menu texts. +# This is necessary in order to get the accesskeys to be the on the first +# character of the menu text instead of after the menu text. +# If a key definition exists for the tag at index n, that key's key will be +# taken as the accesskey, eg. +# +# makes the third tag have the accesskey &tagCmd3.key;. +# In the menuitem's label, this accesskey appears at %1$S below; %2$S will be +# replaced by the tag label. +mailnews.tags.format=%1$S %2$S + +replied=Respondido +forwarded=Reenviado +redirected=Redirigido +new=Nuevo +read=Leído +flagged=Con estrella + +# for junk status picker in search and mail views +junk=No deseado + +# for junk score origin picker in search and mail views +junkScoreOriginPlugin=Plugin +junkScoreOriginFilter=Filtro +junkScoreOriginWhitelist=Lista blanca +junkScoreOriginUser=Usuario +junkScoreOriginImapFlag=Indicador IMAP + +# for the has attachment picker in search and mail views +hasAttachments=Tiene adjuntos + +# for the Tag picker in search and mail views. +tag=Etiquetas + +# LOCALIZATION NOTE(andOthers): +# for multiple authors, add this abbreviation to the first author to indicate +# there are more; for the From column in the threadpane message list. +andOthers=y otros + +# whether to generate display names in last first order +# LOCALIZATION NOTE(mail.addr_book.displayName.lastnamefirst): +# the only valid values are: true OR false (choose from the untranslated English words) +mail.addr_book.displayName.lastnamefirst=false + +# whether to also show phonetic fields in the addressbook +# LOCALIZATION NOTE(mail.addr_book.show_phonetic_fields): +# the only valid values are: true OR false (choose from the untranslated English words) +mail.addr_book.show_phonetic_fields=false + +# valid format options are: +# 1: yyyy/mm/dd +# 2: yyyy/dd/mm +# 3: mm/dd/yyyy +# 4: mm/yyyy/dd +# 5: dd/mm/yyyy +# 6: dd/yyyy/mm +# +# 0: auto-detect the current locale format +# a separator has to be either '/', '-', '.' and the year in Christian year +# otherwise mm/dd/yyyy (option 3) is used +# +mailnews.search_date_format=0 +# separator for search date (e.g. "/", "-"), or empty when search_date_format is zero +mailnews.search_date_separator= +# leading zeros for day and month values, not used if mailnews.search_date_format is not zero +mailnews.search_date_leading_zeros=true -nocachedbodybody2 = El cuerpo de este mensaje no se ha descargado desde el servidor \ +# offline msg +nocachedbodybody2=El cuerpo de este mensaje no se ha descargado desde el servidor \ para leerlo sin conexión. Para leer este mensaje, debe volver a \ conectarse, elegir Sin conexión en el menú Archivo y luego desmarcar \ Trabajar sin conexión. En el futuro, puede seleccionar qué mensajes \ @@ -209,270 +290,484 @@ menú Archivo y luego Descargar/Sincronizar ahora. Puede ajustar las \ preferencias de espacio en disco para evitar descargar mensajes grandes. -acctCentralTitleFormat = %1$S %2$S - %3$S -mailAcctType = Correo -newsAcctType = Noticias -feedsAcctType = Canales - -nocachedbodytitle = Pasar a modo con conexión para ver este mensaje\n - -confirmUnsubscribeTitle = Confirmar la cancelación de la suscripción -confirmUnsubscribeText = ¿Seguro que quiere cancelar la suscripción a %S? -confirmUnsubscribeManyText = ¿Seguro que quiere desuscribirse de estos grupos de noticias? -restoreAllTabs = Restaurar todas las pestañas - -confirmMarkAllFoldersReadTitle = Marcar todas las carpetas como leídas -confirmMarkAllFoldersReadMessage = ¿Está seguro de que quiere marcar como leídos todos los mensajes en todas las carpetas de esta cuenta? - -junkBarMessage = %S piensa que este mensaje es correo basura. -junkBarButton = No es basura -junkBarButtonKey = N -junkBarInfoButton = Saber más -junkBarInfoButtonKey = S - -remoteContentBarMessage = Para proteger su privacidad, %S ha bloqueado el contenido remoto en este mensaje. -remoteContentPrefLabel = Opciones -remoteContentPrefAccesskey = O -remoteContentPrefLabelUnix = Preferencias -remoteContentPrefAccesskeyUnix = P - -remoteAllowResource = Permitir contenido remoto de %S -remoteAllowAll = Permitir contenido remoto del origen listado arriba;Permitir contenido remoto de los #1 orígenes listados arriba - -phishingBarMessage = Este mensaje puede ser fraudulento. -phishingBarPrefLabel = Opciones -phishingBarPrefAccesskey = O -phishingBarPrefLabelUnix = Preferencias -phishingBarPrefAccesskeyUnix = P - -mdnBarIgnoreButton = Ignorar solicitud -mdnBarIgnoreButtonKey = n -mdnBarSendReqButton = Enviar acuse de recibo -mdnBarSendReqButtonKey = E - -draftMessageMsg = Este mensaje es un borrador. -draftMessageButton = Editar -draftMessageButtonKey = r - -openLabel = Abrir -openLabelAccesskey = b -saveLabel = Guardar como… -saveLabelAccesskey = A -detachLabel = Separar adjuntos… -detachLabelAccesskey = D -deleteLabel = Eliminar -deleteLabelAccesskey = r -openFolderLabel = Abrir carpeta contenedora -openFolderLabelAccesskey = c -deleteAttachments = Los siguientes adjuntos se eliminarán permanentemente de este mensaje:\n%S\nEsta acción no se puede deshacer. ¿Desea continuar? -detachAttachments = Los siguientes adjuntos se han guardado correctamente y se eliminarán permanentemente de este mensaje:\n%S\nEsta acción no se puede deshacer. ¿Desea continuar? -deleteAttachmentFailure = Fallo al eliminar los adjuntos seleccionados. -emptyAttachment = Este adjunto parece estar vacío.\nConfírmelo con la persona que envió esto.\nA menudo, los cortafuegos empresariales o los programas antivirus destruyen los adjuntos. -externalAttachmentNotFound = Este adjunto de archivo o enlace separados ya no se encuentra o no está accesible en esta ubicación. - -attachmentCount = #1 adjunto;#1 adjuntos - -attachmentCountSingle = 1 adjunto: - -attachmentSizeUnknown = tamaño desconocido - -attachmentSizeAtLeast = al menos %1$S - -attachmentDisplayNameFormat = %S %S - -attachmentsPrintHeader = Adjuntos: - -unknownHostError = No se pudo conectar con el servidor %S. -connectionRefusedError = No se pudo conectar con el servidor %S; la conexión fue rechazada. -netTimeoutError = La conexión al servidor %S ha superado el tiempo de espera máximo. -netResetError = La conexión al servidor %S se ha reiniciado. -netInterruptError = La conexión al servidor %S se ha interrumpido. - -recipientSearchCriteria = El asunto o destinatario contiene: -fromSearchCriteria = El asunto o remitente contiene: - -biffNotification_message = tiene %1$S mensaje nuevo -biffNotification_messages = tiene %1$S mensajes nuevos - -newMailNotification_message = %1$S ha recibido %2$S mensaje nuevo - -newMailNotification_messages = %1$S ha recibido %2$S mensajes nuevos - -newMailNotification_messagetitle = %1$S de %2$S - -newMailAlert_message = #1 ha recibido #2 mensaje nuevo;#1 ha recibido #2 mensajes nuevos - -quotaPercentUsed = %S%% lleno -percent = %S%% -quotaTooltip2 = Cuota IMAP: %S usados de un total de %S. Pulse para ver detalles. - -confirmViewDeleteTitle = Confirmar -confirmViewDeleteMessage = ¿Seguro que quiere eliminar esta vista? - -confirmSavedSearchTitle = Confirmar eliminación -confirmSavedSearchDeleteMessage = ¿Seguro que desea eliminar esta búsqueda guardada? - -passwordPrompt = Introduzca su contraseña para %1$S en %2$S: - -passwordTitle = Contraseña para el servidor de correo requerida - -openWindowWarningTitle = Confirmar -openWindowWarningConfirmation = Abrir #1 mensaje puede ser lento. ¿Continuar?;Abrir #1 mensajes puede ser lento. ¿Continuar? - -openTabWarningTitle = Confirmar -openTabWarningConfirmation = Abrir #1 mensaje puede ser lento. ¿Continuar?;Abrir #1 mensajes puede ser lento. ¿Continuar? - -tagExists = Ya existe una etiqueta con ese nombre. - -editTagTitle = Editar etiqueta - -editVirtualFolderPropertiesTitle = Editar las propiedades de la búsqueda %S -virtualFolderSourcesChosen = #1 carpeta elegida;#1 carpetas elegidas - -alertNoSearchFoldersSelected = Debe elegir al menos una carpeta en la que buscar para guardar la búsqueda. - -byteAbbreviation2 = %.*f bytes -kiloByteAbbreviation2 = %.*f KB -megaByteAbbreviation2 = %.*f MB -gigaByteAbbreviation2 = %.*f GB -teraByteAbbreviation2 = %.*f TB -petaByteAbbreviation2 = %.*f PB - -folderWithAccount = %1$S - %2$S -folderWithUnreadMsgs = %1$S (%2$S) -folderSummarizedSymbolValue = ▾%S -subfoldersExplanation = %1$S en esta carpeta, %2$S en subcarpetas - -errorOpenMessageForMessageIdTitle = Error al abrir el message-id -errorOpenMessageForMessageIdMessage = Mensaje correspondiente al message-id %S no encontrado - -confirmPhishingTitle = Alerta de correo fraudulento -linkMismatchTitle = Discordancia detectada en enlace -confirmPhishingUrl = %1$S piensa que este mensaje es fraudulento. Los enlaces en el mensaje pueden estar tratando de suplantar la página web que quiere visitar. ¿Seguro que quiere visitar %2$S? -confirmPhishingUrlAlternate = El enlace que acaba de pulsar parece dirigir a otro sitio que el indicado por el texto del enlace. Esto se usa a veces para rastrear si ha pulsado el enlace, pero también podría indicar una técnica fraudulenta.\n\nEl texto del enlace indicaba que este dirigiría a %1$S, pero realmente dirige a %2$S. -confirmPhishingGoAhead = Visitar %1$S de todas formas -confirmPhishingGoDirect = Ir a %1$S - -updatesItem_default = Buscar actualizaciones… -updatesItem_defaultFallback = Buscar actualizaciones… -updatesItem_default.accesskey = C -updatesItem_downloading = Descargando %S… -updatesItem_downloadingFallback = Descargando actualización… -updatesItem_downloading.accesskey = D -updatesItem_resume = Continuar descargando %S… -updatesItem_resumeFallback = Continuar descargando la actualización… -updatesItem_resume.accesskey = d -updatesItem_pending = Aplicar ahora la actualización descargada… -updatesItem_pendingFallback = Aplicar ahora la actualización descargada… -updatesItem_pending.accesskey = A - -folderPaneModeHeader_all = Todas las carpetas -folderPaneModeHeader_unread = Carpetas no leídas -folderPaneModeHeader_favorite = Carpetas favoritas -folderPaneModeHeader_recent = Carpetas recientes -folderPaneModeHeader_smart = Carpetas unificadas -unifiedAccountName = Carpetas unificadas - -moveToFolderAgain = Mover de nuevo a "%1$S" -moveToFolderAgainAccessKey = n -copyToFolderAgain = Copiar de nuevo a "%1$S" -copyToFolderAgainAccessKey = n - -mdnBarMessageNormal = %1$S ha solicitado que se le notifique cuando Vd. lea este mensaje. -mdnBarMessageAddressDiffers = %1$S ha solicitado que se le notifique (en %2$S) cuando Vd. lea este mensaje. - -emptyJunkFolderTitle = Vaciar "%S" -emptyJunkFolderMessage = ¿Eliminar todos los mensajes y subcarpetas de la carpeta Basura? -emptyJunkDontAsk = No volver a preguntarme. -emptyTrashFolderTitle = Vaciar "%S" -emptyTrashFolderMessage = ¿Eliminar todos los mensajes y subcarpetas de la carpeta Papelera? -emptyTrashDontAsk = No volver a preguntarme. - -junkAnalysisPercentComplete = Análisis de correo no deseado completado al %S -processingJunkMessages = Procesando mensajes de correo no deseado +# LOCALIZATION NOTE(acctCentralTitleFormat): %1$S is brand, %2$S is account type, %3$S is account name +acctCentralTitleFormat=%1$S %2$S - %3$S +mailAcctType=Correo +newsAcctType=Noticias +feedsAcctType=Canales + +# LOCALIZATION NOTE(nocachedbodytitle): Do not translate "" or "" in the line below +nocachedbodytitle=Pasar a modo con conexión para ver este mensaje\n + +# mailWindowOverlay.js +confirmUnsubscribeTitle=Confirmar la cancelación de la suscripción +confirmUnsubscribeText=¿Seguro que quiere cancelar la suscripción a %S? +confirmUnsubscribeManyText=¿Seguro que quiere desuscribirse de estos grupos de noticias? +restoreAllTabs=Restaurar todas las pestañas + +confirmMarkAllFoldersReadTitle=Marcar todas las carpetas como leídas +confirmMarkAllFoldersReadMessage=¿Está seguro de que quiere marcar como leídos todos los mensajes en todas las carpetas de esta cuenta? + +# LOCALIZATION NOTE(junkBarMessage): %S is brand +junkBarMessage=%S piensa que este mensaje es correo basura. +junkBarButton=No es basura +junkBarButtonKey=N +junkBarInfoButton=Saber más +junkBarInfoButtonKey=S + +# LOCALIZATION NOTE(remoteContentBarMessage): %S is brand +remoteContentBarMessage=Para proteger su privacidad, %S ha bloqueado el contenido remoto en este mensaje. +remoteContentPrefLabel=Opciones +remoteContentPrefAccesskey=O +remoteContentPrefLabelUnix=Preferencias +remoteContentPrefAccesskeyUnix=P + +# LOCALIZATION NOTE(remoteAllowResource): %S is origin +remoteAllowResource=Permitir contenido remoto de %S +# LOCALIZATION NOTE(remoteAllowAll): Semi-colon list of plural forms. +# See: https://developer.mozilla.org/en/Localization_and_Plurals +# #1 is the number of origins +remoteAllowAll=Permitir contenido remoto del origen listado arriba;Permitir contenido remoto de los #1 orígenes listados arriba + +phishingBarMessage=Este mensaje puede ser fraudulento. +phishingBarPrefLabel=Opciones +phishingBarPrefAccesskey=O +phishingBarPrefLabelUnix=Preferencias +phishingBarPrefAccesskeyUnix=P + +mdnBarIgnoreButton=Ignorar solicitud +mdnBarIgnoreButtonKey=n +mdnBarSendReqButton=Enviar acuse de recibo +mdnBarSendReqButtonKey=E + +draftMessageMsg=Este mensaje es un borrador. +draftMessageButton=Editar +draftMessageButtonKey=r + +# msgHdrViewOverlay.js +openLabel=Abrir +openLabelAccesskey=b +saveLabel=Guardar como… +saveLabelAccesskey=A +detachLabel=Separar adjuntos… +detachLabelAccesskey=D +deleteLabel=Eliminar +deleteLabelAccesskey=r +openFolderLabel=Abrir carpeta contenedora +openFolderLabelAccesskey=c +deleteAttachments=Los siguientes adjuntos se eliminarán permanentemente de este mensaje:\n%S\nEsta acción no se puede deshacer. ¿Desea continuar? +detachAttachments=Los siguientes adjuntos se han guardado correctamente y se eliminarán permanentemente de este mensaje:\n%S\nEsta acción no se puede deshacer. ¿Desea continuar? +deleteAttachmentFailure=Fallo al eliminar los adjuntos seleccionados. +emptyAttachment=Este adjunto parece estar vacío.\nConfírmelo con la persona que envió esto.\nA menudo, los cortafuegos empresariales o los programas antivirus destruyen los adjuntos. +externalAttachmentNotFound=Este adjunto de archivo o enlace separados ya no se encuentra o no está accesible en esta ubicación. + +# LOCALIZATION NOTE (attachmentCount): Semi-colon list of plural forms. +# See: https://developer.mozilla.org/en/Localization_and_Plurals +# #1 number of attachments +attachmentCount=#1 adjunto;#1 adjuntos + +# LOCALIZATION NOTE (attachmentCountSingle): This is the format for the +# attachment header when a message has only one attachment. This is separate +# from attachmentCount above, since attachmentCountSingle typically ends with a +# colon. +attachmentCountSingle=1 adjunto: + +# LOCALIZATION NOTE (attachmentSizeUnknown): The string to show for the total +# size of all attachments when none of the attachments' sizes can be detected. +attachmentSizeUnknown=tamaño desconocido + +# LOCALIZATION NOTE (attachmentSizeAtLeast): The string to show for the total +# size of all attachments when at least one (but not all) of the attachments' +# sizes can't be detected. %1$S is the formatted size. +attachmentSizeAtLeast=al menos %1$S + +# This is the format for prepending accesskeys to the +# each of the attachments in the file|attachments menu: +# ie: 1 file.txt +# 2 another file.txt +attachmentDisplayNameFormat=%S %S + +# This is the heading for the attachment summary when printing an email +attachmentsPrintHeader=Adjuntos: + +# Connection Error Messages +# LOCALIZATION NOTE(unknownHostError): %S is the server name +unknownHostError=No se pudo conectar con el servidor %S. +# LOCALIZATION NOTE(connectionRefusedError): %S is the server name +connectionRefusedError=No se pudo conectar con el servidor %S; la conexión fue rechazada. +# LOCALIZATION NOTE(netTimeoutError): %S is the server name +netTimeoutError=La conexión al servidor %S ha superado el tiempo de espera máximo. +# LOCALIZATION NOTE(netResetError): %S is the server name +netResetError=La conexión al servidor %S se ha reiniciado. +# LOCALIZATION NOTE(netInterruptError): %S is the server name +netInterruptError=La conexión al servidor %S se ha interrumpido. + +recipientSearchCriteria=El asunto o destinatario contiene: +fromSearchCriteria=El asunto o remitente contiene: + +# LOCALIZATION NOTE(biffNotification): %1$S is the number of new messages +biffNotification_message=tiene %1$S mensaje nuevo +biffNotification_messages=tiene %1$S mensajes nuevos + +# LOCALIZATION NOTE(newMailNotification_message): %1$S is the name of the account %2$S is the number of new messages +newMailNotification_message=%1$S ha recibido %2$S mensaje nuevo + +# LOCALIZATION NOTE(newMailNotification_messages): %1$S is the name of the account %2$S is the number of new messages +newMailNotification_messages=%1$S ha recibido %2$S mensajes nuevos + +# LOCALIZATION NOTE(newMailNotification_messagetitle): %1$S is subject of new message and %2$S is sender of new message. +# This is UNIX only +newMailNotification_messagetitle=%1$S de %2$S + +# LOCALIZATION NOTE(newMailAlert_message): +# Semi-colon list of plural forms. See: +# https://developer.mozilla.org/en/docs/Localization_and_Plurals +# #1 is the name of the account, #2 is the number of new messages +newMailAlert_message=#1 ha recibido #2 mensaje nuevo;#1 ha recibido #2 mensajes nuevos + +# For the Quota tab in the mail folder properties dialog +quotaPercentUsed=%S%% lleno +# for quota in main window (commandglue.js) +percent=%S%% +quotaTooltip2=Cuota IMAP: %S usados de un total de %S. Pulse para ver detalles. + +# for message views +confirmViewDeleteTitle=Confirmar +confirmViewDeleteMessage=¿Seguro que quiere eliminar esta vista? + +# for virtual folders +confirmSavedSearchTitle=Confirmar eliminación +confirmSavedSearchDeleteMessage=¿Seguro que desea eliminar esta búsqueda guardada? + +## @name ENTER_PASSWORD_PROMPT +## @loc None +# LOCALIZATION NOTE (passwordPrompt): Do not translate the word %S below. +# Place the word "%S" in your translation where the email address +# or the username should appear +passwordPrompt=Introduzca su contraseña para %1$S en %2$S: + +## @name ENTER_PASSWORD_PROMPT_TITLE +## @loc None +passwordTitle=Contraseña para el servidor de correo requerida + +# for checking if the user really wants to open lots of messages in separate windows. +openWindowWarningTitle=Confirmar +# LOCALIZATION NOTE (openWindowWarningConfirmation): Semi-colon list of plural forms. +# #1 is the number of messages the user is attempting to open. +openWindowWarningConfirmation=Abrir #1 mensaje puede ser lento. ¿Continuar?;Abrir #1 mensajes puede ser lento. ¿Continuar? + +# for checking if the user really wants to open lots of messages in tabs. +openTabWarningTitle=Confirmar +# LOCALIZATION NOTE (openTabWarningConfirmation): Semi-colon list of plural forms. +# #1 is the number of messages the user is attempting to open. +openTabWarningConfirmation=Abrir #1 mensaje puede ser lento. ¿Continuar?;Abrir #1 mensajes puede ser lento. ¿Continuar? + +# for warning the user that a tag they're trying to create already exists +tagExists=Ya existe una etiqueta con ese nombre. + +# title of the edit tag dialog +editTagTitle=Editar etiqueta + +# for the virtual folder list dialog title +# %S is the name of the saved search folder +editVirtualFolderPropertiesTitle=Editar las propiedades de la búsqueda %S +# LOCALIZATION NOTE (foldersChosen): #1 number of chosen folders +virtualFolderSourcesChosen=#1 carpeta elegida;#1 carpetas elegidas + +#alert to inform the user to choose one or more folders to search for a saved search folder +alertNoSearchFoldersSelected=Debe elegir al menos una carpeta en la que buscar para guardar la búsqueda. + +# These are displayed in the message and folder pane windows +# LOCALIZATION NOTE %.*f is the abbreviated size in the appropriate units +byteAbbreviation2=%.*f bytes +kiloByteAbbreviation2=%.*f KB +megaByteAbbreviation2=%.*f MB +gigaByteAbbreviation2=%.*f GB +teraByteAbbreviation2=%.*f TB +petaByteAbbreviation2=%.*f PB + +## LOCALIZATION NOTE(folderWithAccount): +## This is used to show folder name together with an account name. +## %1$S = folder name +## %2$S = account name +folderWithAccount=%1$S - %2$S +## LOCALIZATION NOTE(folderWithUnreadMsgs): +## This is a concatenation of two strings to compose a folder label with unread messages. +## %1$S = folder name +## %2$S = count of unread messages +folderWithUnreadMsgs=%1$S (%2$S) +## LOCALIZATION NOTE(summarizedValue): +## This string shows an indication that the value shown is actually a summary +## accumulated from all subfolders. +## %S = summarized value from all subfolders +folderSummarizedSymbolValue=▾%S +## LOCALIZATION NOTE(subfoldersExplanation): +## This is a tooltip message shown on the values in the numeric folder pane columns. +## %1$S = is the count of messages having the respective property, found in the folder under mouse cursor +## %2$S = is the count of messages having the respective property, found in subfolders of the folder under mouse cursor +subfoldersExplanation=%1$S en esta carpeta, %2$S en subcarpetas + +# Error message if message for a message id wasn't found +errorOpenMessageForMessageIdTitle=Error al abrir el message-id +errorOpenMessageForMessageIdMessage=Mensaje correspondiente al message-id %S no encontrado + +# Warnings to alert users about phishing urls +confirmPhishingTitle=Alerta de correo fraudulento +linkMismatchTitle=Discordancia detectada en enlace +#LOCALIZATION NOTE %1$S is the brand name, %2$S is the host name of the url being visited +confirmPhishingUrl=%1$S piensa que este mensaje es fraudulento. Los enlaces en el mensaje pueden estar tratando de suplantar la página web que quiere visitar. ¿Seguro que quiere visitar %2$S? +#LOCALIZATION NOTE %1$S is the host name of indicated host, %2$S is the host name of the actual host. +confirmPhishingUrlAlternate=El enlace que acaba de pulsar parece dirigir a otro sitio que el indicado por el texto del enlace. Esto se usa a veces para rastrear si ha pulsado el enlace, pero también podría indicar una técnica fraudulenta.\n\nEl texto del enlace indicaba que este dirigiría a %1$S, pero realmente dirige a %2$S. +#LOCALIZATION NOTE $1$S is the host name of the indicated host. +confirmPhishingGoAhead=Visitar %1$S de todas formas +#LOCALIZATION NOTE %1$S is the host name that was displayed to the user. +confirmPhishingGoDirect=Ir a %1$S + +# Check for Updates +# LOCALIZATION NOTE (updatesItem_*): these are alternative labels for Check for Update item in Help menu. +# Which one is used depends on Update process state. +updatesItem_default=Buscar actualizaciones… +updatesItem_defaultFallback=Buscar actualizaciones… +updatesItem_default.accesskey=C +updatesItem_downloading=Descargando %S… +updatesItem_downloadingFallback=Descargando actualización… +updatesItem_downloading.accesskey=D +updatesItem_resume=Continuar descargando %S… +updatesItem_resumeFallback=Continuar descargando la actualización… +updatesItem_resume.accesskey=d +updatesItem_pending=Aplicar ahora la actualización descargada… +updatesItem_pendingFallback=Aplicar ahora la actualización descargada… +updatesItem_pending.accesskey=A + +# Folder Pane Header Title Strings +folderPaneModeHeader_all=Todas las carpetas +folderPaneModeHeader_unread=Carpetas no leídas +folderPaneModeHeader_favorite=Carpetas favoritas +folderPaneModeHeader_recent=Carpetas recientes +folderPaneModeHeader_smart=Carpetas unificadas +unifiedAccountName=Carpetas unificadas + +# Copy / Move to Folder Again +#LOCALIZATION NOTE %1$S is the name of the folder we will move to. moveToFolderAgainAccessKey +# should have the same value as copyToFolderAgainAccessKey as they are the same menu item in the UI +# moveToFolderAgainAccessKey should also be a letter that occurs before %1$S +moveToFolderAgain=Mover de nuevo a "%1$S" +moveToFolderAgainAccessKey=n +#LOCALIZATION NOTE %1$S is the name of the folder we will copy to +# copyToFolderAgainAccessKey +# should have the same value as moveToFolderAgainAccessKey as they are the same menu item in the UI +# copyToFolderAgainAccessKey should also be a letter that occurs before %1$S +copyToFolderAgain=Copiar de nuevo a "%1$S" +copyToFolderAgainAccessKey=n + +#LOCALIZATION NOTE(mdnBarMessageNormal) %1$S is the name of the sender +mdnBarMessageNormal=%1$S ha solicitado que se le notifique cuando Vd. lea este mensaje. +#LOCALIZATION NOTE(mdnBarMessageAddressDiffers) %1$S is the name of the sender, %2$S is the address(es) to send return receipt to +mdnBarMessageAddressDiffers=%1$S ha solicitado que se le notifique (en %2$S) cuando Vd. lea este mensaje. + +# mailCommands.js +emptyJunkFolderTitle=Vaciar "%S" +emptyJunkFolderMessage=¿Eliminar todos los mensajes y subcarpetas de la carpeta Basura? +emptyJunkDontAsk=No volver a preguntarme. +emptyTrashFolderTitle=Vaciar "%S" +emptyTrashFolderMessage=¿Eliminar todos los mensajes y subcarpetas de la carpeta Papelera? +emptyTrashDontAsk=No volver a preguntarme. + +# junkCommands.js +junkAnalysisPercentComplete=Análisis de correo no deseado completado al %S +processingJunkMessages=Procesando mensajes de correo no deseado +# Messenger bootstrapping messages fileNotFoundTitle = Archivo no encontrado +#LOCALIZATION NOTE(fileNotFoundMsg): %S is the filename fileNotFoundMsg = El archivo %S no existe. fileEmptyTitle = Archivo vacío +#LOCALIZATION NOTE(fileEmptyMsg): %S is the filename fileEmptyMsg = El archivo %S está vacío. -headerMoreAddrs = #1 más;#1 más - -headerMoreAddrsTooltip = , y #1 más;, y #1 más - -headertoFieldMe = mí - -headerfromFieldMe = mí - -headerreply-toFieldMe = mí - -headerccFieldMe = mí - -headerbccFieldMe = mí - -expandAttachmentPaneTooltip = Mostrar el panel de adjuntos -collapseAttachmentPaneTooltip = Ocultar el panel de adjuntos - -loadingTab = Cargando… - -confirmMsgDelete.title = Confirmar eliminación -confirmMsgDelete.collapsed.desc = Esto eliminará los mensajes en las conversaciones expandidas. ¿Seguro que desea continuar? -confirmMsgDelete.deleteNoTrash.desc = Esto eliminará los mensajes inmediatamente, sin guardar una copia en la papelera. ¿Seguro que desea continuar? -confirmMsgDelete.deleteFromTrash.desc = Esto eliminará permanentemente los mensajes de la papelera. ¿Está seguro de que quiere continuar? -confirmMsgDelete.dontAsk.label = No volver a preguntarme. -confirmMsgDelete.delete.label = Eliminar - -mailServerLoginFailedTitle = Inicio de sesión fallido -mailServerLoginFailedTitleWithAccount = El inicio de sesión en la cuenta "%S" ha fallado -mailServerLoginFailed2 = El inicio de sesión en el servidor %1$S con el nombre de usuario %2$S ha fallado. -mailServerLoginFailedRetryButton = &Reintentar -mailServerLoginFailedEnterNewPasswordButton = &Introduzca nueva contraseña +# LOCALIZATION NOTE (headerMoreAddrs): semicolon separated list of plural +# forms of the word "more" as used after the number of addresses +# currently hidden while displaying a header such as "to", "cc", or "bcc" +# in the message header box. English has two identical forms here, so it will +# construct strings that look like (for example) "1 more" or "20 more". +# has details +# on this mechanism. +headerMoreAddrs=#1 más;#1 más + +# LOCALIZATION NOTE (headerMoreAddrsTooltip): semicolon separated list of +# plural forms of the phrase ", and #1 more" as used in the tooltip text +# of the more widget displayed in the header pane (see headerMoreAddrs). +# English has two identical forms here, so it will construct strings that +# look like (for example) ", and 1 more" or ", and 20 more". +# has details +# on this mechanism. +headerMoreAddrsTooltip=, y #1 más;, y #1 más + +# LOCALIZATION NOTE (headertoFieldMe): first person prepositional object +# pronoun used in the "to" header of the message header pane. This is also +# used for the fallback case if a header-specific localization is not +# available. +headertoFieldMe=mí + +# LOCALIZATION NOTE (headerfromFieldMe): first person prepositional object +# pronoun used in the "from" header of the message header pane. +headerfromFieldMe=mí + +# LOCALIZATION NOTE (headerreply-toFieldMe): first person prepositional +# object pronoun used in the "reply-to" header of the message header pane. +headerreply-toFieldMe=mí + +# LOCALIZATION NOTE (headerccFieldMe): first person prepositional object +# pronoun used in the "cc" header of the message header pane. +headerccFieldMe=mí + +# LOCALIZATION NOTE (headerbccFieldMe): first person prepositional object +# pronoun used in the "bcc" header of the message header pane. +headerbccFieldMe=mí + +expandAttachmentPaneTooltip=Mostrar el panel de adjuntos +collapseAttachmentPaneTooltip=Ocultar el panel de adjuntos + +# Shown when content tabs are being loaded. +loadingTab=Cargando… + +confirmMsgDelete.title=Confirmar eliminación +confirmMsgDelete.collapsed.desc=Esto eliminará los mensajes en las conversaciones expandidas. ¿Seguro que desea continuar? +confirmMsgDelete.deleteNoTrash.desc=Esto eliminará los mensajes inmediatamente, sin guardar una copia en la papelera. ¿Seguro que desea continuar? +confirmMsgDelete.deleteFromTrash.desc=Esto eliminará permanentemente los mensajes de la papelera. ¿Está seguro de que quiere continuar? +confirmMsgDelete.dontAsk.label=No volver a preguntarme. +confirmMsgDelete.delete.label=Eliminar + +mailServerLoginFailedTitle=Inicio de sesión fallido +# LOCALIZATION NOTE (mailServerLoginFailedTitleWithAccount): +# "%S" is the account name. +mailServerLoginFailedTitleWithAccount=El inicio de sesión en la cuenta "%S" ha fallado +# LOCALIZATION NOTE (mailServerLoginFailed2): +# %1$S is the host name of the server, %2$S is the user name. +mailServerLoginFailed2=El inicio de sesión en el servidor %1$S con el nombre de usuario %2$S ha fallado. +mailServerLoginFailedRetryButton=&Reintentar +mailServerLoginFailedEnterNewPasswordButton=&Introduzca nueva contraseña + +# LOCALIZATION NOTE (threadPane.columnPicker.confirmFolder.noChildren.title): +# When the user selects a folder to apply the currently displayed columns to +# via the "columnPicker.applyToFolder.label" menu option, this is the title of +# the confirmation dialog used to verify they selected the correct folder. This +# is the case in which we apply the columns only to the folder and not to any of +# its children. +threadPane.columnPicker.confirmFolder.noChildren.title=¿Aplicar cambios? +# LOCALIZATION NOTE (threadPane.columnPicker.confirmFolder.noChildren.message): +# When the user selects a folder to apply the currently displayed columns to +# via the "columnPicker.applyToFolder.label" menu option, this is the text of +# the confirmation dialog used to verify they selected the correct folder. The +# string '%S' is replaced with the name of the folder the user selected in +# order to help them confirm they picked what they thought they picked. This +# is the case in which we apply the columns only to the folder and not to any of +# its children. +threadPane.columnPicker.confirmFolder.noChildren.message=¿Aplicar las columnas de la carpeta actual a %S? + +# LOCALIZATION NOTE (threadPane.columnPicker.confirmFolder.withChildren.title): +# When the user selects a folder to apply the currently displayed columns to via +# the "columnPicker.applyToFolderAndChildren.label" menu option, this is the +# title of the confirmation dialog used to verify they selected the correct +# folder. This is the case in which we apply the columns to the folder and all +# of its children. +threadPane.columnPicker.confirmFolder.withChildren.title=¿Aplicar cambios? +# LOCALIZATION NOTE (threadPane.columnPicker.confirmFolder.withChildren.message): +# When the user selects a folder to apply the currently displayed columns to via +# the "columnPicker.applyToFolderAndChildren.label" menu option, this is the +# text of the confirmation dialog used to verify they selected the correct +# folder. The string '%S' is replaced with the name of the folder the user +# selected in order to help them confirm they picked what they thought they +# picked. This is the case in which we apply the columns to the folder and all +# of its children. +threadPane.columnPicker.confirmFolder.withChildren.message=¿Aplicar las columnas de la carpeta actual a %S y sus subcarpetas? + +# LOCALIZATION NOTE (lwthemeInstallRequest.message): %S will be replaced with +# the host name of the site. +lwthemeInstallRequest.message=Este sitio (%S) ha intentado instalar un tema. +lwthemeInstallRequest.allowButton=Permitir +lwthemeInstallRequest.allowButton.accesskey=P + +lwthemePostInstallNotification.message=Se ha instalado un nuevo tema. +lwthemePostInstallNotification.undoButton=Deshacer +lwthemePostInstallNotification.undoButton.accesskey=D +lwthemePostInstallNotification.manageButton=Administrar temas… +lwthemePostInstallNotification.manageButton.accesskey=A + +# troubleshootModeRestart +troubleshootModeRestartPromptTitle=Reiniciar en modo de resolución de problemas +troubleshootModeRestartPromptMessage=El modo de resolución de problemas desactivará todos los complementos y utilizará temporalmente algunas preferencias predeterminadas. \n¿Está seguro de que desea reiniciar? +troubleshootModeRestartButton=Reiniciar + +# LOCALIZATION NOTE (downloadAndInstallButton.label): %S is replaced by the +# version of the update: "Update to 28.0". +update.downloadAndInstallButton.label=Actualizar a %S +update.downloadAndInstallButton.accesskey=U + +# Sanitize +# LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to +# clear" is set to "Everything", the Clear Recent History dialog's title is +# changed to this. See UI mockup and comment 11 at bug 480169 --> +sanitizeDialog2.everything.title=Vaciar todo el historial +sanitizeButtonOK=Limpiar ahora +# LOCALIZATION NOTE (sanitizeEverythingWarning2): Warning that appears when +# "Time range to clear" is set to "Everything" in Clear Recent History dialog, +# provided that the user has not modified the default set of history items to clear. +sanitizeEverythingWarning2=Se eliminará todo el historial. +# LOCALIZATION NOTE (sanitizeSelectedWarning): Warning that appears when +# "Time range to clear" is set to "Everything" in Clear Recent History dialog, +# provided that the user has modified the default set of history items to clear. +sanitizeSelectedWarning=Se eliminarán todos los elementos seleccionados. -threadPane.columnPicker.confirmFolder.noChildren.title = ¿Aplicar cambios? -threadPane.columnPicker.confirmFolder.noChildren.message = ¿Aplicar las columnas de la carpeta actual a %S? - -threadPane.columnPicker.confirmFolder.withChildren.title = ¿Aplicar cambios? -threadPane.columnPicker.confirmFolder.withChildren.message = ¿Aplicar las columnas de la carpeta actual a %S y sus subcarpetas? - -lwthemeInstallRequest.message = Este sitio (%S) ha intentado instalar un tema. -lwthemeInstallRequest.allowButton = Permitir -lwthemeInstallRequest.allowButton.accesskey = P - -lwthemePostInstallNotification.message = Se ha instalado un nuevo tema. -lwthemePostInstallNotification.undoButton = Deshacer -lwthemePostInstallNotification.undoButton.accesskey = D -lwthemePostInstallNotification.manageButton = Administrar temas… -lwthemePostInstallNotification.manageButton.accesskey = A - -update.downloadAndInstallButton.label = Actualizar a %S -update.downloadAndInstallButton.accesskey = U - -sanitizeDialog2.everything.title = Vaciar todo el historial -sanitizeButtonOK = Limpiar ahora -sanitizeEverythingWarning2 = Se eliminará todo el historial. -sanitizeSelectedWarning = Se eliminarán todos los elementos seleccionados. - -learnMoreAboutIgnoreThread = Saber más… +learnMoreAboutIgnoreThread=Saber más… learnMoreAboutIgnoreThreadAccessKey = L -undoIgnoreThread = Deshacer Ignorar conversación -undoIgnoreThreadAccessKey = U -undoIgnoreSubthread = Deshacer Ignorar subconversación -undoIgnoreSubthreadAccessKey = U -ignoredThreadFeedback = Las respuestas a la conversación "#1" no se mostrarán. -ignoredSubthreadFeedback = Las respuestas a la subconversación "#1" no se mostrarán. -ignoredThreadsFeedback = Las respuestas a la conversación que estaba seleccionada no se mostrarán.;Las respuestas a las #1 conversaciones que estaban seleccionadas no se mostrarán. -ignoredSubthreadsFeedback = Las respuestas a la subconversación que estaba seleccionada no se mostrarán.;Las respuestas a las #1 subconversaciones que estaban seleccionadas no se mostrarán. -saveAsType = archivo %S - -openSearch.label = Buscar "%2$S" en %1$S - -openSearch.label.truncated = Buscar "%2$S…" en %1$S - +undoIgnoreThread=Deshacer Ignorar conversación +undoIgnoreThreadAccessKey=U +undoIgnoreSubthread=Deshacer Ignorar subconversación +undoIgnoreSubthreadAccessKey=U +# LOCALIZATION NOTE (ignoredThreadFeedback): #1 is the message thread title +ignoredThreadFeedback=Las respuestas a la conversación "#1" no se mostrarán. +# LOCALIZATION NOTE (ignoredSubthreadFeedback): #1 is the message subthread title +ignoredSubthreadFeedback=Las respuestas a la subconversación "#1" no se mostrarán. +# LOCALIZATION NOTE (ignoredThreadsFeedback): Semi-colon list of plural forms. +# #1 is the number of threads +ignoredThreadsFeedback=Las respuestas a la conversación que estaba seleccionada no se mostrarán.;Las respuestas a las #1 conversaciones que estaban seleccionadas no se mostrarán. +# LOCALIZATION NOTE (ignoredSubthreadsFeedback): Semi-colon list of plural forms. +# #1 is number of subthreads +ignoredSubthreadsFeedback=Las respuestas a la subconversación que estaba seleccionada no se mostrarán.;Las respuestas a las #1 subconversaciones que estaban seleccionadas no se mostrarán. +# LOCALIZATION NOTE (saveAsType): replace %S with the extension of the file to be saved. +saveAsType=archivo %S + +# LOCALIZATION NOTE (openSearch.label): The label used in the autocomplete +# widget to refer to a search on the web for a short string containing at most +# 15 characters. %1$S is the search provider to use. %2$S is the string to +# search for. +openSearch.label=Buscar "%2$S" en %1$S + +# LOCALIZATION NOTE (openSearch.label.truncated): The label used in the +# autocomplete widget to refer to a search on the web for a short string +# containing more than 15 characters. %1$S is the search provider to use. %2$S +# is the string to search for, truncated to 15 characters. +openSearch.label.truncated=Buscar "%2$S…" en %1$S + +# LOCALIZATION NOTE (aboutDialog.architecture.*): +# The sixtyFourBit and thirtyTwoBit strings describe the architecture of the +# current Thunderbird build: 32-bit or 64-bit. These strings are used in parentheses +# after the Thunderbird version in the About dialog, +# e.g.: "48.0.2 (32-bit)" or "51.0a1 (2016-09-05) (64-bit)". aboutDialog.architecture.sixtyFourBit = 64-bit aboutDialog.architecture.thirtyTwoBit = 32-bit errorConsoleTitle = Consola de errores +# LOCALIZATION NOTE (panel.back): +# This is used by screen readers to label the "back" button in various browser +# popup panels, including the sliding subviews of the appmenu. panel.back = Anterior +# LOCALIZATION NOTE (folderErrorAlertTitle): +# %S is a pretty string to identify the folder and account. +# EXAMPLE: Error - Inbox on bob@example.com +folderErrorAlertTitle = Error - %S + diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/migration/migration.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/migration/migration.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/migration/migration.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/migration/migration.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,23 +2,31 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -profileName_format = %S %S +profileName_format=%S %S -1_seamonkey = Preferencias +# Import Sources +1_seamonkey=Preferencias -2_seamonkey = Configuración de la cuenta -2_outlook = Configuración de la cuenta +1_thunderbird=Preferencias -4_seamonkey = Libretas de direcciones -4_outlook = Libreta de direcciones +2_seamonkey=Configuración de la cuenta +2_thunderbird=Configuración de la cuenta +2_outlook=Configuración de la cuenta -8_seamonkey = Entrenamiento de correo no deseado +4_seamonkey=Libretas de direcciones +4_thunderbird=Libretas de direcciones +4_outlook=Libreta de direcciones -16_seamonkey = Contraseñas guardadas +8_seamonkey=Entrenamiento de correo no deseado -32_seamonkey = Otros datos +16_seamonkey=Contraseñas guardadas -64_seamonkey = Carpetas de grupos de noticias +32_seamonkey=Otros datos -128_seamonkey = Carpetas de correo -128_outlook = Carpetas de correo +64_seamonkey=Carpetas de grupos de noticias + +64_thunderbird=Carpetas de grupos de noticias + +128_seamonkey=Carpetas de correo +128_thunderbird=Carpetas de correo +128_outlook=Carpetas de correo diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/morkImportMsgs.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/morkImportMsgs.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/morkImportMsgs.properties 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/morkImportMsgs.properties 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,18 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +# +# The following are used by the Mork import code to display status/error +# and informational messages. +# + +MABFiles = Libretas de direcciones Mork + +# Short name of import module +morkImportName = Base de datos Mork (.mab) + +# Description of import module +morkImportDescription = Importar una libreta de direcciones de SeaMonkey o de versiones anteriores de Thunderbird. + +morkImportSuccess = ¡Correcto! diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/preferences/preferences.properties thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/preferences/preferences.properties --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/preferences/preferences.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/preferences/preferences.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,75 +2,109 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -html_domainsAddDomainTitle = Añadir nombre de dominio HTML -html_domainsAddDomain = Nombre de dominio HTML: -plaintext_domainsAddDomainTitle = Añadir nombre de dominio de texto sin formato -plaintext_domainsAddDomain = Nombre de dominio de texto sin formato: - -domainNameErrorTitle = Error de nombre de dominio -domainDuplicationError = El dominio %S ya existe en las listas de texto sin formato o HTML. - -confirmResetJunkTrainingTitle = Confirmar -confirmResetJunkTrainingText = ¿Seguro que quiere reiniciar los datos de aprendizaje del filtro adaptativo? - -desktopFolderName = Escritorio -myDownloadsFolderName = Mis descargas -chooseAttachmentsFolderTitle = Escoger carpeta +#### Add HTML and Plain Text Domain Names for sendOption +html_domainsAddDomainTitle=Añadir nombre de dominio HTML +html_domainsAddDomain=Nombre de dominio HTML: +plaintext_domainsAddDomainTitle=Añadir nombre de dominio de texto sin formato +plaintext_domainsAddDomain=Nombre de dominio de texto sin formato: + +domainNameErrorTitle=Error de nombre de dominio +#### LOCALIZATION NOTE: do not translate %S +domainDuplicationError=El dominio %S ya existe en las listas de texto sin formato o HTML. + +#### Junk +confirmResetJunkTrainingTitle=Confirmar +confirmResetJunkTrainingText=¿Seguro que quiere reiniciar los datos de aprendizaje del filtro adaptativo? + +#### Downloads +desktopFolderName=Escritorio +myDownloadsFolderName=Mis descargas +chooseAttachmentsFolderTitle=Escoger carpeta #### Applications -fileEnding = fichero %S -saveFile = Guardar archivo +fileEnding=fichero %S +saveFile=Guardar archivo -useApp = Usar %S -useDefault = Usar %S (predeterminado) +# LOCALIZATION NOTE (useApp, useDefault): %S = Application name +useApp=Usar %S +useDefault=Usar %S (predeterminado) + +useOtherApp=Usar otra… +fpTitleChooseApp=Seleccionar aplicación auxiliar +manageApp=Detalles de la aplicación… +alwaysAsk=Preguntar siempre +delete=Eliminar acción +confirmDeleteTitle=Eliminar acción +confirmDeleteText=¿Seguro que quiere eliminar esta acción? + +# LOCALIZATION NOTE (typeDescriptionWithDetails): +# %1$S = type description (for example "Portable Document Format") +# %2$S = details (see below, for example "(application/pdf: .pdf, .pdfx)") +typeDescriptionWithDetails=%1$S %2$S + +# LOCALIZATION NOTE (typeDetailsWithTypeOrExt): +# %1$S = type or extensions (for example "application/pdf", or ".pdf, .pdfx") +typeDetailsWithTypeOrExt=(%1$S) + +# LOCALIZATION NOTE (typeDetailsWithTypeAndExt): +# %1$S = type (for example "application/pdf") +# %2$S = extensions (for example ".pdf, .pdfx") +typeDetailsWithTypeAndExt=(%1$S: %2$S) + +#### Sound Notifications +soundFilePickerTitle=Elegir sonido + +#### Remote content +imagepermissionstext=Puede especificar de qué sitios web se permite cargar imágenes y otro contenido remoto. También puede permitir todo el contenido remoto basándose en la dirección del remitente. Escriba la dirección del sitio o dirección de correo electrónico que quiere administrar y luego pulse Bloquear o Permitir. +imagepermissionstitle=Excepciones - Contenido remoto + +#### Cookies +cookiepermissionstitle=Excepciones - Cookies +cookiepermissionstext=Puede especificar qué sitios web tienen permitido siempre o nunca usar cookies. Escriba la dirección exacta del sitio que quiere administrar y luego pulse Bloquear, Permitir durante la sesión, o Permitir. + +#### Cookie Viewer +hostColon=Servidor: +domainColon=Dominio: +forSecureOnly=Conexiones cifradas únicamente +forAnyConnection=Cualquier tipo de conexión +expireAtEndOfSession=Al final de la sesión + +noCookieSelected= +cookiesAll=Están guardadas en su ordenador las siguientes cookies: +cookiesFiltered=Las siguientes cookies se ajustan a su búsqueda: +# LOCALIZATION NOTE (removeSelectedCookies): +# Semicolon-separated list of plural forms. See: +# https://developer.mozilla.org/en/docs/Localization_and_Plurals +# If you need to display the number of selected elements in your language, +# you can use #1 in your localization as a placeholder for the number. +# For example this is the English string with numbers: +# removeSelectedCookies=Remove #1 Selected;Remove #1 Selected +removeSelectedCookies=Eliminar seleccionado;Eliminar seleccionados +defaultUserContextLabel=Ninguno + +####Preferences::Advanced::Network +#LOCALIZATION NOTE: The next string is for the disk usage of the cache. +# e.g., "Your cache is currently using 200 MB" +# %1$S = size +# %2$S = unit (MB, KB, etc.) +actualDiskCacheSize=Su caché está usando actualmente %1$S %2$S de espacio en disco +actualDiskCacheSizeCalculated=Calculando tamaño de caché… + +# LOCALIZATION NOTE (labelDefaultFont): %S = font name +labelDefaultFont=Predeterminado (%S) +labelDefaultFontUnnamed=Predeterminado + +# LOCALIZATION NOTE (appLocale.label): %S = Name of the application locale, +# e.g. English (United States) +appLocale.label=Idioma de la aplicación: %S +appLocale.accesskey=I +# LOCALIZATION NOTE (rsLocale.label): %S = Name of the locale chosen in regional settings, +# e.g. German (Germany) +rsLocale.label=Localización de ajustes regionales: %S +rsLocale.accesskey=L -useOtherApp = Usar otra… -fpTitleChooseApp = Seleccionar aplicación auxiliar -manageApp = Detalles de la aplicación… -alwaysAsk = Preguntar siempre -delete = Eliminar acción -confirmDeleteTitle = Eliminar acción -confirmDeleteText = ¿Seguro que quiere eliminar esta acción? - -typeDescriptionWithDetails = %1$S %2$S - -typeDetailsWithTypeOrExt = (%1$S) - -typeDetailsWithTypeAndExt = (%1$S: %2$S) - -soundFilePickerTitle = Elegir sonido - -searchEnginePickerTitle = Elegir buscador - -searchEngineType2 = Buscadores - -imagepermissionstext = Puede especificar de qué sitios web se permite cargar imágenes y otro contenido remoto. También puede permitir todo el contenido remoto basándose en la dirección del remitente. Escriba la dirección del sitio o dirección de correo electrónico que quiere administrar y luego pulse Bloquear o Permitir. -imagepermissionstitle = Excepciones - Contenido remoto - -cookiepermissionstitle = Excepciones - Cookies -cookiepermissionstext = Puede especificar qué sitios web tienen permitido siempre o nunca usar cookies. Escriba la dirección exacta del sitio que quiere administrar y luego pulse Bloquear, Permitir durante la sesión, o Permitir. - -hostColon = Servidor: -domainColon = Dominio: -forSecureOnly = Conexiones cifradas únicamente -forAnyConnection = Cualquier tipo de conexión -expireAtEndOfSession = Al final de la sesión - -noCookieSelected = -cookiesAll = Están guardadas en su ordenador las siguientes cookies: -cookiesFiltered = Las siguientes cookies se ajustan a su búsqueda: -removeSelectedCookies = Eliminar seleccionado;Eliminar seleccionados -defaultUserContextLabel = Ninguno - -actualDiskCacheSize = Su caché está usando actualmente %1$S %2$S de espacio en disco -actualDiskCacheSizeCalculated = Calculando tamaño de caché… - -labelDefaultFont = Predeterminado (%S) -labelDefaultFontUnnamed = Predeterminado - -appLocale.label = Idioma de la aplicación: %S -appLocale.accesskey = I -rsLocale.label = Localización de ajustes regionales: %S -rsLocale.accesskey = L +applications-type-pdf = Portable Document Format (PDF) +# LOCALIZATION NOTE (previewInApp): %S = brandShortName +previewInApp=Previsualizar en %S diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/sanitize.dtd thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/sanitize.dtd --- thunderbird-91.7.0+build2/l10n/es-ES/mail/chrome/messenger/sanitize.dtd 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/chrome/messenger/sanitize.dtd 2022-04-15 07:52:23.000000000 +0000 @@ -2,27 +2,35 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/defines.inc thunderbird-91.8.1+build1/l10n/es-ES/mail/defines.inc --- thunderbird-91.7.0+build2/l10n/es-ES/mail/defines.inc 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/defines.inc 2022-04-15 07:52:23.000000000 +0000 @@ -4,6 +4,6 @@ # If non-English locales wish to credit multiple contributors, uncomment this # variable definition and use the format specified. -# #define MOZ_LANGPACK_CONTRIBUTORS Joe Solon Suzy Solon +#define MOZ_LANGPACK_CONTRIBUTORS Proyecto NAVE (http://www.proyectonave.es/) #unfilter emptyLines diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutAddonsExtra.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutAddonsExtra.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutAddonsExtra.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutAddonsExtra.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,10 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +add-on-options-button = + .title = Opciones del complemento +add-on-search-alternative-button-label = Buscar un complemento alternativo +atn-addons-heading-search-input = + .placeholder = Buscar en addons.thunderbird.net +sidebar-preferences-button-title = Preferencias de { -brand-short-name } diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutDialog.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Novedades diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutImport.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutImport.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,17 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + + +## Header + + +## Buttons + + +## Import from app steps + + +## Import dialog + +error-pane-title = Error diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutRights.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutRights.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutRights.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutRights.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -14,6 +14,7 @@ rights-intro-point-6 = Para reproducir ciertos tipos de contenido de víeo, { -brand-short-name } descarga ciertos módulos de descifrado de contenido de terceros. rights-webservices-header = Servicios de información de { -brand-full-name } basados en web rights-webservices = { -brand-full-name } usa servicios de información basados en web ("servicios") para proporcionar algunas de las características ofrecidas para su uso con esta versión binaria de { -brand-short-name } bajo los términos descritos a continuación. Si no quiere usar uno o más de los servicios o los términos que siguen no son aceptables, puede desactivar la característica o servicio(s). Las instrucciones sobre cómo desactivar una característica o servicio concretos pueden encontrarse aquí. Otras características y servicios pueden desactivarse en las preferencias de la aplicación. +rights-webservices2 = { -brand-full-name } usa servicios de información basados en web ("servicios") para proporcionar algunas de las características ofrecidas para su uso con esta versión binaria de { -brand-short-name } bajo los términos descritos a continuación. Si no quiere usar uno o más de los servicios o los términos que siguen no son aceptables, puede desactivar la característica o servicio(s). Las instrucciones sobre cómo desactivar una característica o servicio concretos pueden encontrarse aquí. Otras características y servicios pueden desactivarse en los ajustes de la aplicación. rights-locationawarebrowsing = Navegación basada en ubicación: siempre son a elección del usuario. Nunca se envía información sobre su ubicación sin su permiso. Si desea desactivar la característica por completo, siga esto pasos: rights-locationawarebrowsing-term-1 = En la barra de direcciones, escriba about:config rights-locationawarebrowsing-term-2 = Escriba geo.enabled diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutSupportCalendar.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutSupportCalendar.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutSupportCalendar.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutSupportCalendar.ftl 2022-04-15 07:52:24.000000000 +0000 @@ -0,0 +1,10 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +calendars-table-readonly = Sólo lectura +calendars-table-imip-identity = Identidad iMIP +calendars-table-imip-identity-disabled = iMIP desactivado +calendars-table-imip-identity-account = Cuenta iMIP +calendars-table-organizerid = Id del organizador +calendars-table-forceemailscheduling = Forzar programación de correos diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutSupportChat.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutSupportChat.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/aboutSupportChat.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/aboutSupportChat.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,11 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +chat-title = Cuentas de chat +chat-table-heading-account = ID +chat-table-heading-protocol = Protocolo +chat-table-heading-name = Nombre +chat-table-heading-actions = Acciones +chat-table-copy-debug-log = Copiar registro de depuración + .title = Copiar errores y otros registros de esta cuenta de chat al portapapeles. Puede contener información personal como mensajes de chat. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountCentral.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountCentral.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountCentral.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountCentral.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,57 +4,44 @@ account-central-title = Bienvenido a { -brand-full-name } account-settings = Configuración de la cuenta - +# $accounts (Number) - the number of configured accounts setup-title = Elija qué configurar about-title = Acerca de { -brand-full-name } resources-title = Recursos - release-notes = .title = Acerca de { -brand-full-name } - email-label = Correo .aria-label = Conectar con su cuenta de correo existente email-description = { -brand-short-name } le permite conectar con su cuenta de correo existente, para leer sus mensajes cómoda y eficientemente desde la aplicación. - calendar-label = Calendario .aria-label = Crear un calendario nuevo calendar-description = { -brand-short-name } le permite manejar eventos y le mantiene organizado. Conectar con un calendario remoto hara que todos sus eventos estén sincronizados en todos sus dispositivos. - chat-label = Chat .aria-label = Conectar con su cuenta de chat chat-description = { -brand-short-name } le permite conectarse a múltiples cuentas de mensajería instantánea, ofreciendo compatibilidad con varias plataformas. - filelink-label = Filelink .aria-label = Configurar Filelink filelink-description = { -brand-short-name } le permite configurar una práctica cuenta de enlace con archivos en la nube para enviar fácilmente adjuntos de gran tamaño. - addressbook-label = Libreta de direcciones .aria-label = Crear una libreta de direcciones nueva addressbook-description = { -brand-short-name } le permite organizar todos sus contactos en una libreta de direcciones. También puede conectar con una libreta de direcciones remota para conservar todos sus contactos sincronizados. - feeds-label = Canales .aria-label = Conectar con canales feeds-description = { -brand-short-name } le permite conectarse a canales RSS/Atom para obtener noticias y actualizaciones de todo tipo. - newsgroups-label = Grupos de noticias .aria-label = Conectar con grupos de noticias newsgroups-description = { -brand-short-name } le permite conectar con todos los grupos de noticias que quiera. - import-title = Importar de otro programa import-paragraph = { -brand-short-name } le permite importar mensajes de correo, entradas de libretas de direcciones, suscripciones a canales, preferencias y filtros de otros programas de correo y formatos comunes de libretas de direcciones. - +import-paragraph2 = { -brand-short-name } le permite importar mensajes de correo, entradas de libretas de direcciones, suscripciones a canales, ajustes y filtros de otros programas de correo y formatos comunes de libretas de direcciones. import-label = Importar .aria-label = Importar datos de otros programas - about-paragraph = Thunderbird es el cliente líder de código abierto y multiplataforma de correo y calendario, libre tanto para uso personal como profesional. Queremos que siga siendo seguro y cada día mejor. Una donación nos permitirá contratar desarrolladores, pagar infraestructura y continuar mejorando. - about-paragraph-consider-donation = Thunderbird está financiado por usuarios como usted! Si le gusta Thunderbird, considere hacer una donación. La mejor manera de asegurar que Thunderbird continúa disponible es hacer una donación. - explore-link = Explorar características support-link = Asistencia involved-link = Involucrarse developer-link = Documentación para desarrolladores - read = Leer mensajes compose = Escribir un mensaje nuevo search = Buscar mensajes diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountcreation/accountSetup.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountcreation/accountSetup.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountcreation/accountSetup.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountcreation/accountSetup.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,83 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +## Header + +account-setup-success-title = Cuenta creada correctamente + +## Form fields + +account-setup-password-toggle-hide = + .title = Ocultar contraseña + +## Action buttons + + +## Notifications + + +## Illustrations + +account-setup-step1-image = + .title = Configuración inicial +account-setup-step2-image = + .title = Cargando… +account-setup-step3-image = + .title = Configuración encontrada +account-setup-step4-image = + .title = Error de conexión +account-setup-step5-image = + .title = Cuenta creada +account-setup-privacy-footnote2 = Sus credenciales solo se almacenarán localmente en su ordenador. +account-setup-selection-error = ¿Necesita ayuda? + +## Results area + +# Note: IMAP is the name of a protocol. +account-setup-result-imap = IMAP +account-setup-result-imap-description = Mantener sus carpetas y correos electrónicos sincronizados en su servidor +# Note: POP3 is the name of a protocol. +account-setup-result-pop = POP3 +account-setup-result-pop-description = Mantener sus carpetas y correos electrónicos en su equipo +account-setup-exchange-title = Servidor + +## Error messages + + +## Manual configuration area + +account-setup-hostname-label = Nombre del servidor: +account-setup-port-label = Puerto: + .title = Establecer el puerto a 0 para la detección automática +account-setup-ssl-label = Seguridad de la conexión: + +## Incoming/Outgoing SSL Authentication options + +ssl-cleartext-password-option = Contraseña normal +ssl-encrypted-password-option = Contraseña cifrada + +## Incoming/Outgoing SSL options + + +## Warning insecure server dialog + + +## Warning Exchange confirmation dialog + + +## Dismiss account creation dialog + + +## Alert dialogs + + +## Addon installation section + + +## Success view + + +## Calendar synchronization dialog + diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountManager.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountManager.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountManager.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountManager.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,10 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +open-preferences-sidebar-button = Preferencias de { -brand-short-name } +open-preferences-sidebar-button2 = Ajustes de { -brand-short-name } +open-addons-sidebar-button = Complementos y temas +account-action-add-newsgroup-account = + .label = Añadir una cuenta de grupo de noticias… + .accesskey = n diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountProvisioner.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountProvisioner.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/accountProvisioner.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/accountProvisioner.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,55 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +account-provisioner-tab-title = Obtener una nueva dirección de correo electrónico de un proveedor de servicios +provisioner-searching-icon = + .alt = Buscando… +account-provisioner-title = Crear una nueva dirección de correo electrónico +account-provisioner-description = Utilice los servicios de nuestros socios de confianza para obtener una nueva dirección de correo electrónico privada y segura +account-provisioner-start-help = Los términos de búsqueda utilizados se envían a { -vendor-short-name } (Política de privacidad) y a los proveedores de correo electrónico de terceros mailfence.com (Política de privacidad, Términos de uso) y gandi.net (Política de privacidad, Términos de uso) para encontrar direcciones de correo electrónico disponibles. +account-provisioner-mail-account-title = Comprar una nueva dirección de correo electrónico +account-provisioner-mail-account-description = Thunderbird se ha asociado con Mailfence para ofrecerle un nuevo correo electrónico privado y seguro. Creemos que todo el mundo debería tener un correo electrónico seguro. +account-provisioner-domain-title = Comprar un correo electrónico y un dominio propio +account-provisioner-domain-description = Thunderbird se ha asociado con Gandi para ofrecerle un dominio personalizado. Esto le permite usar cualquier dirección en ese dominio. + +## Forms + +account-provisioner-mail-input = + .placeholder = Su nombre, apodo u otro término de búsqueda +account-provisioner-domain-input = + .placeholder = Su nombre, apodo u otro término de búsqueda +account-provisioner-search-button = Buscar +account-provisioner-button-cancel = Cancelar +account-provisioner-button-existing = Utilizar una cuenta de correo electrónico existente +account-provisioner-button-back = Retroceder + +## Notifications + +account-provisioner-fetching-provisioners = Obteniendo proveedores… +account-provisioner-connection-issues = No se puede comunicar con nuestros servidores de registro. Compruebe su conexión. +account-provisioner-searching-email = Buscando cuentas de correo electrónico disponibles... +account-provisioner-searching-domain = Buscando dominios disponibles... +account-provisioner-searching-error = No hemos podido encontrar ninguna dirección para sugerirle. Intente cambiar los términos de búsqueda. + +## Illustrations + +account-provisioner-step1-image = + .title = Elija qué cuenta crear + +## Search results + +# Variables: +# $count (Number) - The number of domains found during search. +account-provisioner-results-title = + { $count -> + [one] Una dirección disponible encontrada para: + *[other] { $count } direcciones disponibles encontradas para: + } +account-provisioner-mail-results-caption = Puede intentar buscar apodos o algún otro término para encontrar más correos electrónicos. +account-provisioner-domain-results-caption = Puede intentar buscar apodos o algún otro término para encontrar más correos dominios. +account-provisioner-free-account = Gratis +account-provision-price-per-year = { $price } al año +account-provisioner-all-results-button = Mostrar todos los resultados +account-provisioner-open-in-tab-img = + .title = Se abre en una nueva pestaña diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,18 +4,21 @@ carddav-window = .title = Nueva libreta de direcciones CardDAV - +carddav-window-title = Nueva libreta de direcciones CardDAV carddav-dialog = .buttonlabelaccept = Continuar .buttonaccesskeyaccept = C - carddav-username-label = .value = Nombre de usuario: .accesskey = U - +carddav-location-label = + .value = Ubicación: + .accesskey = U +carddav-location = + .default-placeholder = URL o nombre del servidor de la libreta de direcciones carddav-loading = Buscando configuración… +carddav-known-incompatible = Se sabe que { $url } es incompatible con { -brand-short-name }. carddav-connection-error = Fallo al conectar. carddav-none-found = No se han encontrado libretas de direcciones que añadir a la cuenta especificada. carddav-already-added = Todas las libretas de direcciones de la cuenta especificada ha sido añadida. - carddav-available-books = Libretas de direcciones disponibles: diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/abCardDAVProperties.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/abCardDAVProperties.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/abCardDAVProperties.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/abCardDAVProperties.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,29 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +carddav-url-label = + .value = URL de CardDAV: + .accesskey = V +carddav-refreshinterval-label = + .label = Sincronizar: + .accesskey = S +# Variables: +# $minutes (integer) - Number of minutes between address book synchronizations +carddav-refreshinterval-minutes-value = + .label = + { $minutes -> + [one] cada minuto + *[other] cada { $minutes } minutos + } +# Variables: +# $hours (integer) - Number of hours between address book synchronizations +carddav-refreshinterval-hours-value = + .label = + { $hours -> + [one] cada hora + *[other] cada { $hours } horas + } +carddav-readonly-label = + .label = Sólo lectura + .accesskey = r diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/aboutAddressBook.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,146 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +about-addressbook-title = Libreta de direcciones + +## Toolbar + +about-addressbook-toolbar-new-address-book = + .label = Nueva libreta de direcciones +about-addressbook-toolbar-add-carddav-address-book = + .label = Añadir libreta de direcciones CardDAV +about-addressbook-toolbar-add-ldap-address-book = + .label = Añadir libreta de direcciones LDAP +about-addressbook-toolbar-new-contact = + .label = Nuevo contacto +about-addressbook-toolbar-new-list = + .label = Nueva lista +about-addressbook-toolbar-import = + .label = Importar + +## Books + +all-address-books = Todas las libretas de direcciones +about-addressbook-books-context-properties = + .label = Propiedades +about-addressbook-books-context-synchronize = + .label = Sincronizar +about-addressbook-books-context-print = + .label = Imprimir... +about-addressbook-books-context-export = + .label = Exportar... +about-addressbook-books-context-delete = + .label = Eliminar +about-addressbook-books-context-remove = + .label = Eliminar +about-addressbook-books-context-startup-default = + .label = Directorio de inicio predeterminado +about-addressbook-confirm-delete-book-title = Eliminar libreta de direcciones +# Variables: +# $name (String) - Name of the address book to be deleted. +about-addressbook-confirm-delete-book = ¿Está seguro de que desea eliminar { $name } y todos sus contactos? +about-addressbook-confirm-remove-remote-book-title = Eliminar libreta de direcciones +# Variables: +# $name (String) - Name of the remote address book to be removed. +about-addressbook-confirm-remove-remote-book = ¿Está seguro de que desea eliminar { $name }? + +## Cards + +# Variables: +# $name (String) - Name of the address book that will be searched. +about-addressbook-search = + .placeholder = Buscar en { $name } +about-addressbook-search-all = + .placeholder = Buscar en todas las libretas de direcciones +about-addressbook-sort-button = + .title = Cambiar el orden de la lista +about-addressbook-name-format-display = + .label = Nombre para mostrar +about-addressbook-name-format-firstlast = + .label = Nombre y apellidos +about-addressbook-name-format-lastfirst = + .label = Apellidos, nombre +about-addressbook-sort-name-ascending = + .label = Ordenar por nombre (A > Z) +about-addressbook-sort-name-descending = + .label = Ordenar por nombre (Z > A) +about-addressbook-sort-email-ascending = + .label = Ordenar por dirección de correo electrónico (A > Z) +about-addressbook-sort-email-descending = + .label = Ordenar por dirección de correo electrónico (Z > A) +about-addressbook-cards-context-write = + .label = Escribir +about-addressbook-confirm-delete-mixed-title = Eliminar contactos y listas +# Variables: +# $count (Number) - The number of contacts and lists to be deleted. Always greater than 1. +about-addressbook-confirm-delete-mixed = ¿Está seguro de que desea eliminar estos { $count } contactos y listas? +# Variables: +# $count (Number) - The number of lists to be deleted. +about-addressbook-confirm-delete-lists-title = + { $count -> + [one] Eliminar lista + *[other] Eliminar listas + } +# Variables: +# $count (Number) - The number of lists to be deleted. +# $name (String) - The name of the list to be deleted, if $count is 1. +about-addressbook-confirm-delete-lists = + { $count -> + [one] ¿Está seguro de que desea eliminar la lista { $name }? + *[other] ¿Está seguro de que desea eliminar estas { $count } listas? + } +# Variables: +# $count (Number) - The number of contacts to be removed. +about-addressbook-confirm-remove-contacts-title = + { $count -> + [one] Eliminar contacto + *[other] Eliminar contactos + } +# Variables: +# $count (Number) - The number of contacts to be removed. +# $name (String) - The name of the contact to be removed, if $count is 1. +# $list (String) - The name of the list that contacts will be removed from. +about-addressbook-confirm-remove-contacts = + { $count -> + [one] ¿Está seguro de que desea eliminar a { $name } de { $list }? + *[other] ¿Está seguro de que desea eliminar estos { $count } contactos de { $list }? + } +# Variables: +# $count (Number) - The number of contacts to be deleted. +about-addressbook-confirm-delete-contacts-title = + { $count -> + [one] Eliminar contacto + *[other] Eliminar contactos + } +# Variables: +# $count (Number) - The number of contacts to be deleted. +# $name (String) - The name of the contact to be deleted, if $count is 1. +about-addressbook-confirm-delete-contacts = + { $count -> + [one] ¿Está seguro de que desea eliminar el contacto { $name }? + *[other] ¿Está seguro de que desea eliminar estos { $count } contactos? + } + +## Details + +about-addressbook-begin-edit-contact-button = Editar +about-addressbook-cancel-edit-contact-button = Cancelar +about-addressbook-save-edit-contact-button = Guardar +about-addressbook-details-email-addresses-header = Direcciones de correo electrónico +about-addressbook-details-phone-numbers-header = Números de teléfono +about-addressbook-details-home-address-header = Dirección personal +about-addressbook-details-work-address-header = Dirección de trabajo +about-addressbook-details-other-info-header = Otra información +about-addressbook-unsaved-changes-prompt-title = Cambios sin guardar +about-addressbook-unsaved-changes-prompt = ¿Desea guardar los cambios antes de salir de la vista de edición? + +# Photo dialog + +about-addressbook-photo-drop-target = Suelte o pegue una foto aquí, o haga clic para seleccionar un archivo. +about-addressbook-photo-drop-loading = Cargando foto… +about-addressbook-photo-drop-error = No se ha podido cargar la foto. +about-addressbook-photo-filepicker-title = Seleccionar un archivo de imagen +about-addressbook-photo-discard = Descartar la foto existente +about-addressbook-photo-cancel = Cancelar +about-addressbook-photo-save = Guardar diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/fieldMapImport.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/fieldMapImport.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/addressbook/fieldMapImport.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/addressbook/fieldMapImport.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,12 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import-ab-csv-window = + .title = Importar libreta de direcciones desde un archivo de texto +import-ab-csv-dialog-title = Importar libreta de direcciones desde un archivo de texto +# $recordNumber (Number) - The current record number of the preview data. +import-ab-csv-preview-record-number = Vista previa de la importación de datos para el registro { $recordNumber } +import-ab-csv-dialog = + .buttonlabelaccept = Importar + .buttonaccesskeyaccept = I diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/chat.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/chat.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/chat.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/chat.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,39 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +chat-joining-chat-icon2 = + .alt = Unirse al chat +chat-left-chat-icon2 = + .alt = Salir del chat +chat-participant-owner-role-icon2 = + .alt = Propietario +chat-participant-administrator-role-icon2 = + .alt = Administrador +chat-participant-moderator-role-icon2 = + .alt = Moderador +chat-participant-voiced-role-icon2 = + .alt = El participante puede publicar mensajes +chat-verify-identity = + .label = Verificar identidad + .accesskey = i +chat-identity-verified = + .label = Identidad ya verificada +chat-buddy-identity-status = Confianza del cifrado +chat-buddy-identity-status-verified = Verificada +chat-buddy-identity-status-unverified = No verificada + +## Conversation invite notification box + +# This string appears in a notification bar at the top of the Contacts window +# when someone invited the user to a multi user chat conversation, to request +# the user to confirm they want to join the chat. +# Variables: +# $conversation (String) - Name of the conversation the user is invited to. +chat-conv-invite-label = Le han invitado a chatear en { $conversation } +chat-conv-invite-accept = + .label = Aceptar + .accesskey = A +chat-conv-invite-deny = + .label = Rechazar + .accesskey = R diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/chat-verifySession.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/chat-verifySession.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/chat-verifySession.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/chat-verifySession.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,14 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +verify-window-title = Verificar identidad +# Variables: +# $subject (String) - a human readable identifier for the other side of the verification flow. +verify-window-subject-title = Verificar la identidad de { $subject } +verify-dialog = + .buttonlabelaccept = Coinciden + .buttonaccesskeyaccept = n + .buttonlabelextra2 = No coinciden + .buttonaccesskeyextra2 = d +challenge-label = Verifique que la cadena mostrada coincide con la que se muestra en el otro extremo. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/compactFoldersDialog.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/compactFoldersDialog.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/compactFoldersDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/compactFoldersDialog.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,20 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +compact-dialog-window = + .title = Compactar carpetas + .style = width: 50em; +compact-dialog = + .buttonlabelaccept = Compactar ahora + .buttonaccesskeyaccept = C + .buttonlabelcancel = Recordármelo más tarde + .buttonaccesskeycancel = R + .buttonlabelextra1 = Saber más… + .buttonaccesskeyextra1 = S +# Variables: +# $data (String): The amount of space to be freed, formatted byte, MB, GB, etc., based on the size. +compact-dialog-message = { -brand-short-name } debe realizar un mantenimiento regular de los archivos para mejorar el rendimiento de sus carpetas de mensajes. Esta acción recuperará { $data } de espacio en disco sin cambiar sus mensajes. Para permitir que { -brand-short-name } haga esto automáticamente en el futuro sin preguntar, marque la casilla de abajo antes de elegir ‘{ compact-dialog.buttonlabelaccept }’. +compact-dialog-never-ask-checkbox = + .label = Compactar automáticamente las carpetas en el futuro + .accesskey = a diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/exportDialog.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/exportDialog.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/exportDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/exportDialog.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,14 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +export-dialog-brand-name = { -brand-product-name } +export-dialog-title = Exportar +export-dialog = + .buttonlabelaccept = Siguiente +export-dialog-button-finish = Finalizar +export-dialog-file-picker = Exportar a un archivo zip +export-dialog-description1 = Exportar cuentas de correo, mensajes de correo, libretas de direcciones y ajustes a un archivo zip. +export-dialog-desc2 = Cuando sea necesario, puede importar el archivo zip para restaurar su perfil. +export-dialog-exporting = Exportando… +export-dialog-exported = ¡Exportado! diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/importDialog.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/importDialog.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/importDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/importDialog.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,21 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Short name of the import module +thunderbird-import-name = Thunderbird +# Description of the import module +thunderbird-import-description = Importar correo desde un directorio de perfil de Thunderbird. +import-from-thunderbird-zip = + .label = Thunderbird (copia de seguridad del perfil exportada; archivo ZIP de menos de 2 GiB) + .accesskey = Z +import-from-thunderbird-dir = + .label = Thunderbird (carpeta del perfil) + .accesskey = T +import-select-profile-zip = Seleccionar un directorio de perfil comprimido +import-select-profile-dir = Seleccionar un directorio de perfil +zip-file-too-big-title = Archivo ZIP demasiado grande +zip-file-too-big-message = El archivo ZIP seleccionado tiene un tamaño superior a 2 GiB. Descomprima primero el archivo y después impórtelo desde la carpeta descomprimida. +wizardpage-failed = + .label = Importación fallida +wizardpage-failed-message = La importación ha fallado inesperadamente, puede que haya más información en la consola de errores. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/menubar.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/menubar.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,17 +2,77 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -## View Menu +toolbar-context-menu-menu-bar = + .toolbarname = Barra de menú + .accesskey = m ## Tools Menu +# Since v89 we dropped the platforms distinction between Options or Preferences +# and consolidated everything with Preferences. +menu-tools-preferences = + .label = Preferencias + .accesskey = P +menu-tools-settings = + .label = Ajustes + .accesskey = e +menu-addons-and-themes = + .label = Complementos y temas + .accesskey = a + ## Help Menu +menu-help-enter-troubleshoot-mode = + .label = Modo de resolución de problemas… + .accesskey = r +menu-help-exit-troubleshoot-mode = + .label = Desactivar el modo de resolución de problemas + .accesskey = o +menu-help-more-troubleshooting-info = + .label = Más información para solucionar problemas + .accesskey = M + ## Mail Toolbar +toolbar-junk-button = + .label = Basura + .tooltiptext = Marcar los mensajes seleccionados como basura +toolbar-not-junk-button = + .label = No es basura + .tooltiptext = Marcar los mensajes seleccionados como no basura +toolbar-delete-button = + .label = Eliminar + .tooltiptext = Eliminar mensajes o carpetas seleccionadas +toolbar-undelete-button = + .label = Recuperar + .tooltiptext = Recuperar mensajes seleccionados + ## View +menu-view-repair-text-encoding = + .label = Reparar la codificación de texto + .accesskey = c + ## View / Layout +mail-uidensity-label = + .label = Densidad + .accesskey = D +mail-uidensity-compact = + .label = Compacto + .accesskey = C +mail-uidensity-normal = + .label = Normal + .accesskey = N +mail-uidensity-touch = + .label = Táctil + .accesskey = T +menu-spaces-toolbar-button = + .label = Barra de herramientas de espacios + .accesskey = s + ## File +file-new-newsgroup-account = + .label = Cuenta de grupo de noticias… + .accesskey = n diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/migration.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/migration.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/migration.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/migration.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,15 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +migration-progress-header = Preparando { -brand-short-name }… + +## Migration tasks + + +# These strings are displayed to the user if a migration is taking a long time. +# They should be short (no more than a handful of words) and in the present tense. + +migration-task-test-fast = Probando un cambio rápido +migration-task-test-slow = Probando un cambio lento +migration-task-test-progress = Probando la barra de progreso diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/backupKeyPassword.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/backupKeyPassword.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/backupKeyPassword.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/backupKeyPassword.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,3 +2,13 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +set-password-window = + .title = Elija una contraseña para hacer una copia de seguridad de su clave OpenPGP +set-password-legend = Elegir una contraseña +set-password-message = La contraseña que establezca aquí sirve para proteger el archivo de la copia de seguridad de la clave secreta de OpenPGP que va a generar. Debe establecer esta contraseña para continuar con la copia de seguridad. +set-password-backup-pw = + .value = Contraseña para la copia de seguridad de la clave secreta: +set-password-repeat-backup-pw = + .value = Contraseña para la copia de seguridad de la clave secreta (otra vez): +set-password-reminder = ¡Importante! Si olvida la contraseña de la copia de seguridad de la clave secreta, no podrá restaurar esta copia de seguridad más adelante. Guárdela en un lugar seguro. +password-quality-meter = Medidor de calidad de la contraseña diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/changeExpiryDlg.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/changeExpiryDlg.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/changeExpiryDlg.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/changeExpiryDlg.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,3 +2,17 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +openpgp-change-key-expiry-title = + .title = Cambiar la caducidad de la clave +info-will-expire = Esta clave está actualmente configurada para caducar el { $date }. +info-already-expired = Esta clave ya ha caducado. +info-does-not-expire = Esta clave está actualmente configurada para no caducar nunca. +info-explanation-1 = Cuando una clave caduca, ya no es posible usarla para cifrar contenido o realizar una firma digital. +info-explanation-2 = Si quiere usar esta clave durante un período de tiempo más largo, cambie su fecha de caducidad y comparta de nuevo la clave pública con sus compañeros de conversación. +expire-dont-change = + .label = No cambiar la fecha de caducidad +expire-never-label = + .label = La clave nunca caducará +expire-in-label = + .label = La clave caducará en: +expire-in-months = Meses diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/composeKeyStatus.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/composeKeyStatus.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/composeKeyStatus.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/composeKeyStatus.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,3 +2,23 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +openpgp-compose-key-status-intro-need-keys = Para enviar un mensaje cifrado de extremo a extremo, debe obtener y aceptar una clave pública para cada destinatario. +openpgp-compose-key-status-keys-heading = Disponibilidad de claves OpenPGP: +openpgp-compose-key-status-title = + .title = Seguridad de mensajes OpenPGP +openpgp-compose-key-status-recipient = + .label = Destinatario +openpgp-compose-key-status-status = + .label = Estado +openpgp-compose-key-status-open-details = Administrar las claves del destinatario seleccionado... +openpgp-recip-good = aceptar +openpgp-recip-missing = no hay ninguna clave disponible +openpgp-recip-none-accepted = no hay ninguna clave aceptada +openpgp-compose-general-info-alias = { -brand-short-name } normalmente requiere que la clave pública del destinatario contenga un ID de usuario que coincida con la dirección de correo electrónico. Esto se puede anular utilizando las reglas de alias de destinatarios de OpenPGP. +openpgp-compose-general-info-alias-learn-more = Saber más +openpgp-compose-alias-status-direct = + { $count -> + [one] asignado a una clave de alias + *[other] asignado a { $count } claves de alias + } +openpgp-compose-alias-status-error = clave de alias inutilizable/no disponible diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/keyWizard.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/keyWizard.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/keyWizard.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/keyWizard.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,9 +2,13 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + ## Generate key section + ## Import Key section +openpgp-import-fingerprint-label = Huella digital + ## External Key section diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/msgReadStatus.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/msgReadStatus.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/msgReadStatus.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/msgReadStatus.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,5 +2,61 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + ## Message Header Encryption Button +message-header-show-security-info-key = S +# $type (String) - the shortcut key defined in the message-header-show-security-info-key +message-security-button = + .title = + { PLATFORM() -> + [macos] Mostrar seguridad del mensaje (⌃ ⌘ { message-header-show-security-info-key }) + *[other] Mostrar seguridad del mensaje (Ctrl+Alt+{ message-header-show-security-info-key }) + } +openpgp-view-signer-key = + .label = Ver la clave del firmante +openpgp-view-your-encryption-key = + .label = Ver su clave de descifrado +openpgp-openpgp = OpenPGP +openpgp-no-sig = Sin firma digital +openpgp-no-sig-info = Este mensaje no contiene la firma digital del remitente. La ausencia de una firma digital significa que el mensaje podría haber sido enviado por alguien que finge tener esta dirección de correo electrónico. También es posible que el mensaje haya sido alterado mientras circulaba por la red. +openpgp-uncertain-sig = Firma digital incierta +openpgp-invalid-sig = Firma digital no válida +openpgp-good-sig = Firma digital correcta +openpgp-sig-uncertain-no-key = Este mensaje contiene una firma digital, pero no está claro si es correcta. Para comprobar la firma, necesita obtener una copia de la clave pública del remitente. +openpgp-sig-uncertain-uid-mismatch = Este mensaje contiene una firma digital, pero se detectó una discrepancia. El mensaje fue enviado desde una dirección de correo electrónico que no coincide con la clave pública del firmante. +openpgp-sig-uncertain-not-accepted = Este mensaje contiene una firma digital, pero aún no ha decidido si acepta la clave del firmante. +openpgp-sig-invalid-rejected = Este mensaje contiene una firma digital, pero previamente decidió rechazar la clave del firmante. +openpgp-sig-invalid-technical-problem = Este mensaje contiene una firma digital, pero se detectó un error técnico. O el mensaje se ha dañado o alguien más lo ha modificado. +openpgp-sig-valid-unverified = Este mensaje incluye una firma digital válida de una clave que ya ha aceptado. Sin embargo, aún no ha comprobado que la clave sea propiedad del remitente. +openpgp-sig-valid-verified = Este mensaje incluye una firma digital válida de una clave verificada. +openpgp-sig-valid-own-key = Este mensaje incluye una firma digital válida de su clave personal. +openpgp-sig-key-id = ID de la clave del firmante: { $key } +openpgp-sig-key-id-with-subkey-id = ID de la clave del firmante: { $key } (ID de la subclave: { $subkey }) +openpgp-enc-key-id = Su ID de la clave de descifrado: { $key } +openpgp-enc-key-with-subkey-id = Su ID de la clave de descifrado: { $key } (ID de la subclave: { $subkey }) +openpgp-enc-none = El mensaje no está cifrado +openpgp-enc-none-label = Este mensaje no fue cifrado antes de ser enviado. La información que se manda a Internet sin cifrar puede ser vista por otras personas mientras llega a su destino. +openpgp-enc-invalid-label = No se puede descifrar el mensaje +openpgp-enc-invalid = Este mensaje fue cifrado antes de ser enviado, pero no se puede descifrar. +openpgp-enc-clueless = Hay problemas desconocidos con este mensaje cifrado. +openpgp-enc-valid-label = El mensaje está cifrado +openpgp-enc-valid = Este mensaje fue cifrado antes de ser enviado. El cifrado asegura que el mensaje solo pueda ser leído por los destinatarios previstos. +openpgp-unknown-key-id = Clave desconocida +openpgp-other-enc-additional-key-ids = Además, el mensaje se cifró para los propietarios de las siguientes claves: +openpgp-other-enc-all-key-ids = El mensaje fue cifrado para los propietarios de las siguientes claves: +openpgp-message-header-encrypted-ok-icon = + .alt = Descifrado con éxito +openpgp-message-header-encrypted-notok-icon = + .alt = Descifrado fallido +openpgp-message-header-signed-ok-icon = + .alt = Firma correcta +# Mismatch icon is used for notok state as well +openpgp-message-header-signed-mismatch-icon = + .alt = Firma errónea +openpgp-message-header-signed-unknown-icon = + .alt = Estado de firma desconocido +openpgp-message-header-signed-verified-icon = + .alt = Firma verificada +openpgp-message-header-signed-unverified-icon = + .alt = Firma no verificada diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,3 +2,27 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +openpgp-one-recipient-status-title = + .title = Seguridad de mensajes OpenGPG +openpgp-one-recipient-status-status = + .label = Estado +openpgp-one-recipient-status-key-id = + .label = ID de clave +openpgp-one-recipient-status-created-date = + .label = Creado +openpgp-one-recipient-status-expires-date = + .label = Caduca +openpgp-one-recipient-status-open-details = + .label = Abrir detalles y editar aceptación… +openpgp-one-recipient-status-discover = + .label = Descubrir clave nueva o actualizada +openpgp-one-recipient-status-instruction1 = Para enviar un mensaje cifrado de extremo a extremo a un destinatario, necesita obtener su clave pública OpenPGP y marcarla como aceptada. +openpgp-one-recipient-status-instruction2 = Para obtener su clave pública, impórtela desde el correo electrónico que le han enviado y que la incluye. También puede intentar descubrir su clave pública en un directorio. +openpgp-key-own = Aceptada (clave personal) +openpgp-key-secret-not-personal = Inutilizable +openpgp-key-verified = Aceptada (verificada) +openpgp-key-unverified = Aceptada (no verificada) +openpgp-key-undecided = No aceptada (indecisa) +openpgp-key-rejected = No aceptada (rechazada) +openpgp-key-expired = Caducada +openpgp-intro = Claves públicas disponibles para { $key } diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/openpgp-frontend.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/openpgp-frontend.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/openpgp-frontend.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/openpgp-frontend.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,3 +2,48 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +openpgp-manage-keys-openpgp-cmd = + .label = Administrador de claves OpenPGP + .accesskey = O +openpgp-ctx-decrypt-open = + .label = Descifrar y abrir + .accesskey = D +openpgp-ctx-decrypt-save = + .label = Descifrar y guardar como... + .accesskey = c +openpgp-ctx-import-key = + .label = Importar clave OpenGPG + .accesskey = I +openpgp-ctx-verify-att = + .label = Verificar firma + .accesskey = V +openpgp-has-sender-key = Este mensaje afirma contener la clave pública OpenPGP del remitente. +openpgp-be-careful-new-key = Advertencia: La nueva clave pública de OpenPGP de este mensaje difiere de las claves públicas que aceptó anteriormente para { $email }. +openpgp-import-sender-key = + .label = Importar... +openpgp-search-keys-openpgp = + .label = Descubrir clave OpenPGP +openpgp-missing-signature-key = Este mensaje se firmó con una clave que aún no tiene. +openpgp-search-signature-key = + .label = Descubrir... +# Don't translate the terms "OpenPGP" and "MS-Exchange" +openpgp-broken-exchange-opened = Este es un mensaje de OpenPGP que aparentemente fue dañado por MS-Exchange y no se puede reparar porque se abrió desde un archivo local. Copie el mensaje en una carpeta de correo para intentar una reparación automática. +openpgp-broken-exchange-info = Este es un mensaje de OpenPGP que aparentemente fue dañado por MS-Exchange. Si el contenido del mensaje no se muestra como se esperaba, puede intentar una reparación automática. +openpgp-broken-exchange-repair = + .label = Reparar mensaje +openpgp-broken-exchange-wait = Espere... +openpgp-cannot-decrypt-because-mdc = + Este es un mensaje cifrado que utiliza un mecanismo antiguo y vulnerable. + Podría haber sido modificado mientras estaba en tránsito, con la intención de robar su contenido. + Para evitar este riesgo, no se muestran el contenido. +openpgp-cannot-decrypt-because-missing-key = La clave secreta necesaria para descifrar este mensaje no está disponible. +openpgp-partially-signed = + Sólo una parte de este mensaje se firmó digitalmente mediante OpenPGP. + Si pulsa el botón de comprobación, se ocultarán las partes no protegidas y se mostrará el estado de la firma digital. +openpgp-partially-encrypted = + Solo un subconjunto de este mensaje se cifró con OpenPGP. + Las partes legibles del mensaje que ya se muestran no se cifraron. + Si pulsa el botón de descifrar, se mostrará el contenido de las partes cifradas. +openpgp-reminder-partial-display = Recordatorio: El mensaje que se muestra a continuación es sólo una parte del mensaje original. +openpgp-partial-verify-button = Verificar +openpgp-partial-decrypt-button = Descifrar diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/openpgp.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/openpgp.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/openpgp/openpgp.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/openpgp/openpgp.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -1,13 +1,35 @@ - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +openpgp-key-man-copy-fprs = + .label = + { $count -> + [one] Copiar huella digital al portapapeles + *[other] Copiar huellas digitales al portapapeles + } + .accesskey = h +openpgp-key-man-ctx-copy-fprs = + .label = + { $count -> + [one] Huella digital + *[other] Huellas digitales + } + .accesskey = H +openpgp-key-man-fingerprint-label = + .label = Huella digital +openpgp-key-details-fingerprint-label = Huella digital +openpgp-acceptance-verified-label = + .label = Sí, he verificado en persona que esta clave tiene la huella digital correcta. + ## e2e encryption settings + ## OpenPGP Key selection area + ## Account settings export output + # Strings used in enigmailMessengerOverlay.js diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/add-finger.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/add-finger.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Añadir huella de la clave OTR - +otr-add-finger-title = Añadir huella digital de la clave OTR # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Introduzca la huella de la clave OTR para { $name }. - otr-add-finger-fingerprint = Huella: -otr-add-finger-tooltip-error = Carácter no válido introducido. So se permiten las letras ABCDEF y números - +otr-add-finger-tooltip-error = Carácter no válido introducido. Solo se permiten las letras ABCDEF y números otr-add-finger-input = .placeholder = La huella de 40 caracteres de longitud de la clave OTR diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/am-im-otr.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/am-im-otr.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/am-im-otr.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/am-im-otr.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -6,6 +6,7 @@ .label = Cifrado extremo-a-extremo account-otr-label = Mensajería Off-the-Record (OTR) account-otr-description = { -brand-short-name } permite cifrado extremo-a-extremo de las conversaciones uno-a-uno. Esto impide que terceros se infiltren en una conversación. El cifrado extremo-a-extremo solo puede usarse cuando la otra persona también usa software que admite OTR. +account-otr-description2 = { -brand-short-name } permite cifrado extremo-a-extremo de las conversaciones uno-a-uno basadas en OTR. Esto impide que terceros se infiltren en una conversación. Este tipo de cifrado extremo-a-extremo solo puede usarse cuando la otra persona también usa software que admite OTR. otr-encryption-title = Cifrado verificado otr-encryption-caption = Para permitir que otros verifiquen su identidad en los chats OTR, compara su propia huella OTR usando un canal de comunicación externo (fuera-de-banda). otr-fingerprint-label = Su huella: @@ -15,10 +16,13 @@ otr-settings-title = Ajustes OTR otr-log = .label = Incluir mensajes cifrados OTR en los registros de conversaciones - +otr-require-encryption = + .label = Requerir cifrado de extremo a extremo para conversaciones uno a uno otr-require-encryption-info = Al requerir cifrado de extremo a extremo, los mensajes en conversaciones uno a uno no se enviarán a menos que puedan ser cifrados. Los mensajes recibidos no cifrados no se mostrarán como parte de la conversación normal ni tampoco serán registrados. - +otr-verify-nudge = + .label = Siempre recordarme verificar un contacto no verificado +otr-not-yet-available = no disponible todavía diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/auth.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/auth.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/auth.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/auth.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -5,33 +5,36 @@ otr-auth = .title = Verificar identidad del contacto .buttonlabelaccept = Verificar - # Variables: # $name (String) - the screen name of a chat contact person auth-title = Verificar la identidad de { $name } - # Variables: # $own_name (String) - the user's own screen name auth-your-fp-value = Huella de usted, { $own_name }: - # Variables: # $their_name (String) - the screen name of a chat contact auth-their-fp-value = Huella de { $their_name }: - auth-help = Verificar la identidad de un contacto ayuda a asegurar que la conversación es verdaderamente privada, haciendo muy difícil que un tercero se infiltre o manipule la conversación. - +auth-help-title = Ayuda para verificación +auth-question-received = Ésta es la pregunta que hace su contacto: auth-yes = .label = Sí - auth-no = .label = No - auth-verified = He verificado que esta es realmente la huella correcta. - +auth-manual-verification = Verificación manual de huella digital +auth-question-and-answer = Pregunta y respuesta +auth-shared-secret = Secreto compartido +auth-manual-verification-label = + .label = { auth-manual-verification } +auth-question-and-answer-label = + .label = { auth-question-and-answer } +auth-shared-secret-label = + .label = { auth-shared-secret } +auth-manual-instruction = Póngase en contacto con su interlocutor a través de algún otro canal autenticado, como el correo electrónico firmado OpenPGP o por teléfono. Deben comunicarse mutuamente sus huellas digitales. (Una huella digital es una suma de verificación que identifica una clave de cifrado). Si la huella digital coincide, debe indicar en el cuadro de diálogo a continuación que verificó la huella digital. auth-how = ¿Cómo le gustaría verificar la identidad de su contacto? - +auth-qa-instruction = Piense en una pregunta para la que solo usted y su contacto conozcan la respuesta. Escriba la pregunta y la respuesta, luego espere a que su contacto escriba la respuesta. Si las respuestas no coinciden, el canal de comunicación que está utilizando puede estar bajo vigilancia. +auth-secret-instruction = Piense en un secreto conocido solo por usted y su contacto. No use la misma conexión a Internet para intercambiar el secreto. Escriba el secreto, luego espere a que su contacto lo introduzca. Si los secretos no coinciden, el canal de comunicación que está utilizando puede estar bajo vigilancia. auth-question = Introduzca una pregunta: - auth-answer = Introduzca la respuesta (se distinguen mayúsculas y minúsculas): - auth-secret = Introduzca el secreto: diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/finger.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/finger.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -5,16 +5,15 @@ otr-finger = .buttonlabelaccept = Cerrar .title = Huellas OTR vistas previamente - +otr-finger-title = Huellas digitales OTR vistas previamente finger-intro = Huellas de claves OTR de conversaciones cifradas extremo-a-extremo anteriores. - +finger-screen-name = + .label = Contacto finger-verified = .label = Estado de verificación finger-fingerprint = .label = Huella - finger-remove = .label = Eliminar seleccionadas - finger-remove-all = .label = Eliminar todas diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/otr.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/otr.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/otr.ftl 2022-03-07 21:37:33.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/otr.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,17 +2,71 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-encryption-required-part1 = Ha intentado enviar un mensaje no cifrado a { $name }. Como norma, los mensajes no cifrados no están permitidos. +msgevent-encryption-required-part2 = Intentando iniciar una conversación privada. El mensaje será reenviado cuando la conversación privada se inicie. +msgevent-encryption-error = Ha ocurrido un error al cifrar el mensaje. El mensaje no ha sido enviado. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-connection-ended = { $name } ya cerró la conexión cifrada con usted. Para evitar que envíe accidentalmente un mensaje sin cifrado, su mensaje no se envió. Por favor finalice su conversación cifrada o reiníciela. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-setup-error = Ha ocurrido un error al configurar una conversación privada con { $name }. +# Do not translate 'OTR' (name of an encryption protocol) +msgevent-msg-reflected = Está recibiendo sus propios mensajes OTR. Está intentando hablar consigo mismo o alguien le está reenviado sus propios mensajes. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-msg-resent = El último mensaje a { $name } ha sido reenviado. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-not-private = El mensaje cifrado recibido de { $name } no se puede leer ya que en este momento no se está comunicando de forma privada. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-unreadable = Ha recibido un mensaje cifrado ilegible de { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-malformed = Ha recibido un mensaje de datos con formato incorrecto de { $name }. +# A Heartbeat is a technical message used to keep a connection alive. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-log-heartbeat-rcvd = Mensaje Heartbeat recibido de { $name }. +# A Heartbeat is a technical message used to keep a connection alive. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-log-heartbeat-sent = Mensaje Heartbeat enviado a { $name }. +# Do not translate 'OTR' (name of an encryption protocol) +msgevent-rcvdmsg-general-err = Ha ocurrido un error inesperado al intentar proteger su conversación usando OTR. +# Variables: +# $name (String) - the screen name of a chat contact person +# $msg (string) - the message that was received. +msgevent-rcvdmsg-unencrypted = El siguiente mensaje recibido de { $name } no estaba cifrado: { $msg } +# Do not translate 'OTR' (name of an encryption protocol) +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-unrecognized = Ha recibido un mensaje OTR no reconocido de { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-for-other-instance = { $name } ha enviado un mensaje destinado a una sesión diferente. Si inició sesión varias veces, otra sesión puede haber recibido el mensaje. +# Variables: +# $name (String) - the screen name of a chat contact person +context-gone-secure-private = Se ha iniciado una conversación privada con { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +context-gone-secure-unverified = Se inició una conversación cifrada pero no verificada con { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +context-still-secure = Se ha actualizado correctamente la conversación cifrada con { $name }. error-enc = Ha sucedido un error al cifrar el mensaje. - +# Variables: +# $name (String) - the screen name of a chat contact person +error-not-priv = Ha enviado datos cifrados a { $name }, que no los esperaba. error-unreadable = Ha transmitido un mensaje cifrado ilegible. error-malformed = Ha transmitido un mensaje con datos mal formados. - resent = [reenviado] - # Variables: # $name (String) - the screen name of a chat contact person tlv-disconnected = { $name } ha finalizado su conversación cifrada con usted; debería hacer lo mismo. - # Do not translate "Off-the-Record" and "OTR" which is the name of an encryption protocol # Make sure that this string does NOT contain any numbers, e.g. like "3". # Variables: diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/otr/otrUI.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/otr/otrUI.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -6,69 +6,60 @@ refresh-label = Refrescar la conversación cifrada auth-label = Verificar la identidad de su contacto reauth-label = Verificar de nuevo la identidad de su contacto - auth-cancel = Cancelar - +auth-cancel-access-key = C auth-error = Ha sucedido un error al verificar la identidad de su contacto. auth-success = Se ha completado correctamente la verificación de la identidad de su contacto. +auth-success-them = Su contacto ha verificado con éxito su identidad. Es posible que también usted desee verificar su identidad haciendo su propia pregunta. auth-fail = Ha fallado la verificación de la identidad de su contacto. auth-waiting = Esperando que el contacto complete la verificación… - finger-verify = Verificar - +finger-verify-access-key = V +finger-ignore = Ignorar +finger-ignore-access-key = I # Do not translate 'OTR' (name of an encryption protocol) buddycontextmenu-label = Añadir huella OTR - # Variables: # $name (String) - the screen name of a chat contact person alert-start = Intentando iniciar una conversación cifrada con { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-refresh = Intentando refrescar la conversación cifrada con { $name }. - +# Variables: +# $name (String) - the screen name of a chat contact person +alert-gone-insecure = La conversación cifrada con { $name } finalizó. # Variables: # $name (String) - the screen name of a chat contact person finger-unseen = La identidad de { $name } no se ha verificado aún. No es posible una infiltración por casualidad, pero con cierto esfuerzo alguien podría estar escuchando. Evite la vigilancia verificando la identidad de su contacto. - # Variables: # $name (String) - the screen name of a chat contact person finger-seen = { $name } está contactando con usted desde un equipo no reconocido. No es posible una infiltración por casualidad, pero con cierto esfuerzo alguien podría estar escuchando. Evite la vigilancia verificando la identidad de su contacto. - +state-not-private = La conversación actual no es privada. +state-generic-not-private = La conversación actual no es privada. # Variables: # $name (String) - the screen name of a chat contact person state-unverified = La conversación actual está cifrada pero no es privada, dado que la identidad de { $name } aún no ha sido verificada. - +state-generic-unverified = La conversación actual está cifrada pero no es privada, ya que algunas identidades aún no han sido verificadas. # Variables: # $name (String) - the screen name of a chat contact person state-private = La identidad de { $name } ha sido verificada. La conversación actual está cifrada y es privada. - +state-generic-private = La conversación actual está cifrada y es privada. # Variables: # $name (String) - the screen name of a chat contact person state-finished = { $name } ha finalizado su conversación privada con usted; debería hacer lo mismo. - +state-not-private-label = Insegura state-unverified-label = No verificada state-private-label = Privada state-finished-label = Finalizada - # Variables: # $name (String) - the screen name of a chat contact person verify-request = { $name } ha solicitado la verificación de su identidad. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-private = Ha verificado la identidad de { $name }. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-unverified = La identidad de { $name } no ha sido verificada. - -verify-title = Verificar la identidad de su contacto -error-title = Error -success-title = Cifrado extremo a extremo -fail-title = No se puede verificar -waiting-title = Solicitud de verificación enviada - # Do not translate 'OTR' (name of an encryption protocol) # Variables: # $error (String) - contains an error message that describes the cause of the failure diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/policies/policies-descriptions.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/policies/policies-descriptions.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/policies/policies-descriptions.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/policies/policies-descriptions.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,6 +2,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + ## The Enterprise Policies feature is aimed at system administrators ## who want to deploy these settings across several Thunderbird installations ## all at once. This is traditionally done through the Windows Group Policy @@ -10,137 +11,83 @@ ## in the documentation section in about:policies. policy-3rdparty = Establecer políticas a las que WebExtensions puedan acceder a través de chrome.storage.managed. - policy-AppAutoUpdate = Activar o desactivar la actualización automática de la aplicación. - policy-AppUpdateURL = Establecer una URL de actualización personalizada. - policy-Authentication = Configurar identificación integrada en los sitios web que la admitan. - +policy-BackgroundAppUpdate2 = Activar o desactivar la actualización en segundo plano. policy-BlockAboutAddons = Bloquear el acceso al administrador de complementos (about:addons). - policy-BlockAboutConfig = Bloquear el acceso a la página about:config. - policy-BlockAboutProfiles = Bloquear el acceso a la página about:profiles. - policy-BlockAboutSupport = Bloquear el acceso a la página about:support. - policy-CaptivePortal = Activar o desactivar la compatibilidad con un portal cautivo. - policy-CertificatesDescription = Añadir certificados o usar certificados incluidos de serie. - policy-Cookies = Permitir o denegar a los sitios web enviar cookies. - +policy-DisableBuiltinPDFViewer = Desactivar PDF.js, el visor de PDF integrado en { -brand-short-name }. policy-DisabledCiphers = Desactivar cifrados. - policy-DefaultDownloadDirectory = Establecer el directorio de descargas predeterminado. - policy-DisableAppUpdate = Impedir que { -brand-short-name } se actualice. - policy-DisableDefaultClientAgent = Impedir que el agente de cliente por omisión lleve a cabo ninguna acción. Solo es aplicable a Windows; otras plataformas no tienen el agente. - policy-DisableDeveloperTools = Bloquear el acceso a las herramientas de desarrollo. - policy-DisableFeedbackCommands = Desactivar las opciones para enviar información desde el menú Ayuda (Enviar opiniones e Informar de sitio fraudulento). - policy-DisableForgetButton = Impedir el acceso al botón Olvidar. - policy-DisableFormHistory = No recordar el historial de búsquedas y formularios. - policy-DisableMasterPasswordCreation = Si Verdadero, no se puede crear una contraseña maestra. - policy-DisablePasswordReveal = No permitir que se revelen las contraseñas en las credenciales guardadas. - policy-DisableProfileImport = Desactivar la opción de menú para importar datos desde otra aplicación. - policy-DisableSafeMode = Desactivar la funcionalidad para reiniciar en modo seguro. Nota: la tecla Mayúsculas para entrar en modo seguro solo puede desactivarse en Windows usando políticas de grupo. - policy-DisableSecurityBypass = Impedir que el usuario se salte ciertas advertencias de seguridad. - policy-DisableSystemAddonUpdate = Impedir que { -brand-short-name } instale y actualice complementos de sistema. - policy-DisableTelemetry = Desactivar Telemetry. - policy-DisplayMenuBar = Mostrar la barra de menú por defecto. - policy-DNSOverHTTPS = Configurar DNS sobre HTTPS. - policy-DontCheckDefaultClient = Desactivar la comprobación de cliente predeterminado al iniciar. - policy-DownloadDirectory = Establecer y bloquear el directorio de descargas. - # “lock” means that the user won’t be able to change this setting policy-EnableTrackingProtection = Activar o desactivar el bloqueo de contenido e impedir su modificación. - # “lock” means that the user won’t be able to change this setting policy-EncryptedMediaExtensions = Activar o desactivar las extensiones cifradas de medios y opcionalmente bloquearlos. - # A “locked” extension can’t be disabled or removed by the user. This policy # takes 3 keys (“Install”, ”Uninstall”, ”Locked”), you can either keep them in # English or translate them as verbs. policy-Extensions = Instalar, desinstalar o bloquear exensiones. La opción Instalar admite URL o rutas como parámetros. Las opciones Desinstalar y Bloquear admiten ID de extensiones. - policy-ExtensionSettings = Administrar todos los aspectos de la instalación de extensiones. - policy-ExtensionUpdate = Activar o desactivar actualizaciones automáticas de extensiones. - +policy-Handlers = Configurar gestores de aplicación predeterminados. policy-HardwareAcceleration = Si falso, desactivar la aceleración hardware. - policy-InstallAddonsPermission = Permitir a ciertos sitios web instalar complementos. - policy-LegacyProfiles = Disable the feature enforcing a separate profile for each installation. ## Do not translate "SameSite", it's the name of a cookie attribute. policy-LegacySameSiteCookieBehaviorEnabled = Activar el ajuste de comportamiento de la cookie SameSite por omisión anterior. - policy-LegacySameSiteCookieBehaviorEnabledForDomainList = Revertir al comportamiento anterior de SameSite para las cookies de sitios específicos. ## policy-LocalFileLinks = Permitir a sitios web específicos enlazar a archivos locales. - +policy-ManualAppUpdateOnly = Permitir solo actualizaciones manuales y no notificar al usuario acerca de actualizaciones. policy-NetworkPrediction = Activar o desactivar la predicción de red (precarga DNS). - policy-OfferToSaveLogins = Forzar el ajuste para permitir a { -brand-short-name } ofrecer recordar los inicios de sesión y contraseñas guardadas. Se aceptan valores Verdadero y Falso. - policy-OfferToSaveLoginsDefault = Configurar el valor por omisión para permitir a { -brand-short-name } ofrecer recordar las credenciales y contraseñas guardadas. Se aceptan valores Verdadero y Falso. - policy-OverrideFirstRunPage = Reemplazar la página de primera ejecución. Establezca esta política en blanco si quiere desactivar la página de primera ejecución. - policy-OverridePostUpdatePage = Reemplazar la página "Novedades" tras una actualización. Establezca esta política en blanco si quiere desactivar la página tras una actualización. - policy-PasswordManagerEnabled = Activar el guardado de contraseñas en el administrador de contraseñas. - # PDF.js and PDF should not be translated policy-PDFjs = Desactivar o configurar PDF.js, el visor PDF incorporado en { -brand-short-name }. - policy-Permissions2 = Configurar permisos de la cámara, micrófono, ubicación, notificaciones y autorreproducción. - policy-Preferences = Establecer y bloquear el valor de un subconjunto de preferencias. - +policy-PrimaryPassword = Requerir o evitar el uso de una contraseña maestra. policy-PromptForDownloadLocation = Preguntar dónde guardar los archivos al guardar. - policy-Proxy = Configurar los ajustes de proxy. - policy-RequestedLocales = Configurar la lista de idiomas solicitados para la aplicación en orden de preferencia. - policy-SanitizeOnShutdown2 = Limpiar los datos de navegación al cerrar. - policy-SearchEngines = Configurar los ajustes de buscadores. Esta política solo está disponible en la versión de asistencia extendida (ESR). - policy-SearchSuggestEnabled = Activar o desactivar sugerencias de búsqueda. - # For more information, see https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11/Module_Installation policy-SecurityDevices = Instalar módulos PKCS #11. - policy-SSLVersionMax = Establecer la versión SSL máxima. - policy-SSLVersionMin = Establecer la versión SSL mínima. - policy-SupportMenu = Añadir una opción de menú personalizada en el menú Ayuda. - policy-UserMessaging = No mstrar ciertos mensajes al usuario. - # “format” refers to the format used for the value of this policy. policy-WebsiteFilter = Bloquear la visita de sitios web. Vea la documentación para más detalles sobre el formato. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/am-copies.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/am-copies.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/am-copies.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/am-copies.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +account-prefs-show-address-row-description = Deje el campo de dirección en blanco para que siempre aparezca la fila de dirección al iniciar un nuevo mensaje. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/am-im.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/am-im.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/am-im.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/am-im.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,3 +2,20 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +account-settings-title = Configuración de autenticación +account-channel-title = Canales predeterminados +chat-autologin = + .label = Iniciar sesión al inicio +chat-encryption-generic = Genérico +chat-encryption-log = + .label = Incluir mensajes cifrados de extremo a extremo en los registros de conversaciones +chat-encryption-label = Cifrado de extremo a extremo nativo +chat-encryption-description = { $protocol } proporciona cifrado de extremo a extremo para mensajes de chat. Esto evita que terceros espíen la conversación. Es posible que se necesite una configuración adicional a continuación para que el cifrado sea operativo. +chat-encryption-status = Estado del cifrado +chat-encryption-placeholder = Cifrado no inicializado. +chat-encryption-sessions = Sesiones +chat-encryption-sessions-description = Para que el cifrado de extremo a extremo funcione correctamente, tiene que confiar en las otras sesiones conectadas actualmente a su cuenta. Se requiere interacción con el otro cliente para verificar una sesión. Verificar una sesión puede dar lugar a que todas las sesiones en las que confía también sean de confianza para { -brand-short-name }. +chat-encryption-session-verify = verificar + .title = Verificar la identidad de esta sesión +chat-encryption-session-trusted = confiable + .title = La identidad de esta sesión está comprobada diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/connection.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/connection.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/connection.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/connection.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,20 +4,16 @@ connection-dns-over-https-url-resolver = Usar proveedor .accesskey = r - # Variables: # $name (String) - Display name or URL for the DNS over HTTPS provider connection-dns-over-https-url-item-default = .label = { $name } (predeterminado) .tooltiptext = Usar la URL predeterminada para resolver DNS sobre HTTPS - connection-dns-over-https-url-custom = .label = Personalizado .accesskey = P .tooltiptext = Introducir su URL preferida para resolver DNS sobre HTTPS - connection-dns-over-https-custom-label = Personalizado - connection-dialog-window = .title = Configuración de conexión .style = @@ -25,84 +21,74 @@ [macos] width: 52em !important *[other] width: 59em !important } - +connection-disable-extension = + .label = Desactivar extensión +disable-extension-button = Desactivar extensión +# Variables: +# $name (String) - The extension that is controlling the proxy settings. +# +# The extension-icon is the extension's icon, or a fallback image. It should be +# purely decoration for the actual extension name, with alt="". +proxy-settings-controlled-by-extension = Una extensión, { $name }, está controlando cómo se conecta { -brand-short-name } a Internet. connection-proxy-legend = Configurar proxies para el acceso a Internet - proxy-type-no = .label = Sin proxy .accesskey = i - proxy-type-wpad = .label = Autodetectar configuración del proxy para esta red .accesskey = t - proxy-type-system = .label = Usar configuración de proxy del sistema .accesskey = U - proxy-type-manual = .label = Configuración manual del proxy: .accesskey = m - proxy-http-label = .value = Proxy HTTP: .accesskey = h - http-port-label = .value = Puerto: .accesskey = p - proxy-http-sharing = .label = Usar también este proxy para HTTPS .accesskey = x - proxy-https-label = .value = Proxy HTTPS: .accesskey = S - ssl-port-label = .value = Puerto: .accesskey = o - proxy-socks-label = .value = Servidor SOCKS: .accesskey = c - socks-port-label = .value = Puerto: .accesskey = e - proxy-socks4-label = .label = SOCKS v4 .accesskey = k - proxy-socks5-label = .label = SOCKS v5 .accesskey = v - proxy-type-auto = .label = URL para la configuración automática del proxy: .accesskey = A - proxy-reload-label = .label = Recargar .accesskey = R - no-proxy-label = .value = No usar proxy para: .accesskey = n - no-proxy-example = Ejemplo: .mozilla.org, .net.nz, 192.168.1.0/24 - +# Do not translate "localhost", "127.0.0.1/8" and "::1". (You can translate "and".) +connection-proxy-noproxy-localhost-desc-2 = Las conexiones a localhost, 127.0.0.1/8 y ::1 nunca pasan por proxy. proxy-password-prompt = .label = No solicitar identificación si la contraseña está guardada .accesskey = d .tooltiptext = Esta opción le identifica sin ningún mensaje ante los proxis cuando ha guardado credenciales para ellos. Se le preguntará en caso de que falle el inicio de sesión. - proxy-remote-dns = .label = DNS proxy al usar SOCKS v5 .accesskey = 5 - proxy-enable-doh = .label = Activar DNS sobre HTTPS .accesskey = v diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/dock-options.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/dock-options.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/dock-options.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/dock-options.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -5,22 +5,20 @@ dock-options-window-dialog = .title = Opciones del icono de la aplicación .style = width: 42em; - +dock-options-show-badge = + .label = Mostrar icono de insignia + .accesskey = M bounce-system-dock-icon = .label = Animar el icono de la aplicación cuando llegue un mensaje nuevo .accesskey = A - dock-icon-legend = Insignia del icono de la aplicación - dock-icon-show-label = .value = Icono insignia de aplicación con: - count-unread-messages-radio = .label = Cuenta de mensajes no leídos .accesskey = u - count-new-messages-radio = .label = Cuenta de mensajes nuevos .accesskey = C - notification-settings-info = Puede desactivar la insignia en el panel Notificaciones de las preferencias del sistema. +notification-settings-info2 = Puede desactivar la insignia en el panel Notificaciones de los ajustes del sistema. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/fonts.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/fonts.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/fonts.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/fonts.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,21 +4,17 @@ fonts-window-close = .key = w - # Variables: # $name {string, "Arial"} - Name of the default font fonts-label-default = .label = ({ $name }) por omisión fonts-label-default-unnamed = .label = Por omisión - fonts-encoding-dialog-title = .title = Tipografías y codificación - fonts-language-legend = .value = Tipos de letra para: .accesskey = t - fonts-proportional-label = .value = Proporcional: .accesskey = P @@ -89,41 +85,35 @@ default-font-serif = .label = Serif - default-font-sans-serif = .label = Sans Serif - +font-size-proportional-label = + .value = Tamaño: + .accesskey = m font-size-monospace-label = .value = Tamaño: .accesskey = m - font-serif-label = .value = Serif: .accesskey = S - font-sans-serif-label = .value = Sans-serif: .accesskey = n - font-monospace-label = .value = Tipo fijo: .accesskey = M - font-min-size-label = .value = Tamaño de letra mínimo: .accesskey = z - min-size-none = .label = Ninguno ## Fonts in message font-control-legend = Control de tipografía - use-document-fonts-checkbox = .label = Permitir a los mensajes usar otros tipos .accesskey = o - use-fixed-width-plain-checkbox = .label = Usar tipografías de ancho fijo para mensajes de texto sin formato .accesskey = x @@ -131,17 +121,13 @@ ## Language settings text-encoding-legend = Codificación de texto - text-encoding-description = Fijar la codificación por omisión para enviar y recibir mensajes - font-outgoing-email-label = .value = Correo saliente: .accesskey = s - font-incoming-email-label = .value = Correo entrante: .accesskey = e - default-font-reply-checkbox = .label = Cuando sea posible, usar la codificación por omisión en las respuestas .accesskey = u diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/new-tag.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/new-tag.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/new-tag.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/new-tag.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,8 +4,9 @@ tag-dialog-window = .title = Nueva etiqueta - tag-name-label = .value = Nombre de etiqueta: .accesskey = t - +tag-color-label = + .value = Color: + .accesskey = C diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/offline.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/offline.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/offline.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/offline.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,51 +4,39 @@ offline-dialog-window = .title = Configuración sin conexión - autodetect-online-label = .label = Seguir automáticamente el estado de conexión detectado - .accesskey = a - + .accesskey = d +offline-preference-startup-label = Indicar manualmente el estado al iniciar: status-radio-remember = .label = Recordar el estado de conexión anterior .accesskey = R - status-radio-ask = .label = Preguntarme el estado de conexión .accesskey = d - status-radio-always-online = .label = Con conexión .accesskey = x - status-radio-always-offline = .label = Sin conexión .accesskey = o - going-online-label = ¿Enviar mensajes pendientes al pasar a modo con conexión? - going-online-auto = .label = Sí .accesskey = S - going-online-not = .label = No .accesskey = N - going-online-ask = .label = Preguntarme .accesskey = P - going-offline-label = ¿Descargar mensajes para su uso desconectado al pasar a modo sin conexión? - going-offline-auto = .label = Siempre .accesskey = m - going-offline-not = .label = Nunca .accesskey = c - going-offline-ask = .label = Preguntarme .accesskey = e diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/passwordManager.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/passwordManager.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/passwordManager.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/passwordManager.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -6,6 +6,10 @@ .title = Credenciales guardadas window-close = .key = w +focus-search-primary-shortcut = + .key = f +focus-search-alt-shortcut = + .key = k copy-provider-url-cmd = .label = Copiar URL .accesskey = y @@ -44,7 +48,9 @@ import = .label = Importar… .accesskey = I - +password-close-button = + .label = Cerrar + .accesskey = C show-passwords = .label = Mostrar contraseñas .accesskey = P @@ -67,12 +73,10 @@ # This message can be seen by trying to show or copy the passwords. password-os-auth-dialog-message = Verique su identidad para mostrar las contraseñas guardadas. - # This message can be seen by trying to show or copy the passwords. # The macOS strings are preceded by the operating system with "Thunderbird is trying to " # and includes subtitle of "Enter password for the user "xxx" to allow this." These # notes are only valid for English. Please test in your locale. password-os-auth-dialog-message-macosx = mostrar las contraseñas guardadas - # Don't change this label. password-os-auth-dialog-caption = { -brand-full-name } diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/permissions.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/permissions.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/permissions.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/permissions.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -5,49 +5,39 @@ permissions-reminder-window = .title = Excepciones .style = width: 52em; - +permission-preferences-close-window = + .key = w website-address-label = .value = Dirección del sitio web: .accesskey = D - block-button = .label = Bloquear .accesskey = B - allow-session-button = .label = Permitir durante la sesión .accesskey = P - allow-button = .label = Permitir .accesskey = m - treehead-sitename-label = .label = Sitio - treehead-status-label = .label = Estado - remove-site-button = .label = Eliminar sitio .accesskey = E - remove-all-site-button = .label = Eliminar todos los sitios .accesskey = a - cancel-button = .label = Cancelar .accesskey = C - save-button = .label = Guardar cambios .accesskey = G - permission-can-label = Permitir permission-can-access-first-party-label = Permitir solo primeras partes permission-can-session-label = Permitir durante la sesión permission-cannot-label = Bloquear - invalid-uri-message = Introduzca un nombre de servidor válido invalid-uri-title = Introducido un nombre de servidor no válido diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/preferences.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,6 +4,8 @@ close-button = .aria-label = Cerrar +preferences-doc-title = Preferencias +preferences-doc-title2 = Ajustes category-list = .aria-label = Categorías pane-general-title = General @@ -82,6 +84,8 @@ # Continue is the cancel button so pressing escape or using a platform standard # method of closing the UI will not discard the update. update-in-progress-cancel-button = &Continuar +account-button = Configuración de la cuenta +open-addons-sidebar-button = Complementos y temas ## OS Authentication dialog @@ -112,15 +116,16 @@ .label = Rest. valores predet. .accesskey = R default-search-engine = Buscador predeterminado -add-search-engine = - .label = Añadir desde archivo - .accesskey = s add-web-search-engine = .label = Agregar… .accesskey = A remove-search-engine = .label = Eliminar .accesskey = l +add-opensearch-provider-title = Añadir proveedor OpenSearch +add-opensearch-provider-text = Introduzca la URL del proveedor de OpenSearch a añadir. Utilice la URL directa del archivo de descripción de OpenSearch o una URL donde se pueda descubrir automáticamente. +adding-opensearch-provider-failed-title = No se ha podido añadir el proveedor OpenSearch +adding-opensearch-provider-failed-text = No se ha podido añadir el proveedor OpenSearch para { $url }. minimize-to-tray-label = .label = Cuando se minimiza { -brand-short-name }, moverlo a la bandeja del sistema .accesskey = m @@ -140,12 +145,19 @@ .label = Opciones del icono de la aplicación… .accesskey = c notification-settings = Las alertas y el sonido predeterminado pueden desactivarse en el panel Notificaciones de las preferencias del sistema. +notification-settings2 = Las alertas y el sonido predeterminado se pueden desactivar en el panel de notificaciones de los ajustes del sistema. animated-alert-label = .label = Mostrar una alerta .accesskey = M customize-alert-label = .label = Personalizar… .accesskey = P +biff-use-system-alert = + .label = Usar la notificación del sistema +tray-icon-unread-label = + .label = Mostrar un icono en la barra de tareas para mensajes no leídos + .accesskey = t +tray-icon-unread-description = Recomendado cuando se utilizan botones pequeños en la barra de tareas mail-system-sound-label = .label = Sonido del sistema predeterminado para correo nuevo .accesskey = S @@ -177,6 +189,9 @@ smooth-scrolling-label = .label = Usar desplazamiento suave .accesskey = d +browsing-gtk-use-non-overlay-scrollbars = + .label = Mostrar siempre las barras de desplazamiento + .accesskey = z system-integration-legend = Integración con el sistema always-check-default = .label = Comprobar siempre al iniciar si { -brand-short-name } es el cliente de correo por omisión @@ -234,6 +249,9 @@ offline-compact-folder = .label = Compactar todas las carpetas cuando se ahorren más de .accesskey = C +offline-compact-folder-automatically = + .label = Preguntar siempre vez antes de compactar + .accesskey = P compact-folder-size = .value = MB en total @@ -296,12 +314,10 @@ quoted-text-color = .label = Color: .accesskey = o -type-column-label = - .label = Tipo de contenido - .accesskey = T -action-column-label = - .label = Acción - .accesskey = A +search-handler-table = + .placeholder = Filtrar tipos de contenido y acciones +type-column-header = Tipo de contenido +action-column-header = Acción save-to-label = .label = Guardar archivos en .accesskey = G @@ -656,9 +672,31 @@ chat-variant-label = .value = Vaiante: .accesskey = V +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input = + .style = width: 15.4em + .placeholder = Buscar en preferencias ## Preferences UI Search Results +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input2 = + .style = width: 15.4em + .placeholder = Buscar en ajustes ## Settings UI Search Results @@ -669,4 +707,10 @@ [windows] ¡Lo sentimos! No hay resultados en Opciones para “”. *[other] ¡Lo sentimos! No hay resultados en Preferencias para “”. } +# `` will be replaced by the search term. +search-results-empty-message2 = + { PLATFORM() -> + [windows] ¡Lo sentimos! No hay resultados para "" en los ajustes. + *[other] ¡Lo sentimos! No hay resultados para "" en los ajustes. + } search-results-help-link = ¿Necesita ayuda? Visite la ayuda de { -brand-short-name } diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/receipts.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/receipts.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/receipts.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/receipts.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,48 +4,35 @@ receipts-dialog-window = .title = Acuses de recibo - -return-receipt-checkbox = +return-receipt-checkbox-control = .label = Al enviar mensajes, solicitar siempre un acuse de recibo - .acceskey = A - + .accesskey = v receipt-arrive-label = Cuando llegue un acuse de recibo: - -receipt-leave-radio = +receipt-leave-radio-control = .label = Dejarlo en mi bandeja de entrada - .acceskey = D - -receipt-move-radio = - .label = Moverlo a mi carpeta "Enviados" - .acceskey = M - + .accesskey = D +receipt-move-radio-control = + .label = Moverlo a mi carpeta “Enviados” + .accesskey = M receipt-request-label = Cuando reciba una solicitud de acuse de recibo: - -receipt-return-never-radio = +receipt-return-never-radio-control = .label = Nunca enviar acuse de recibo - .acceskey = N - -receipt-return-some-radio = + .accesskey = n +receipt-return-some-radio-control = .label = Permitir acuse de recibo para algunos mensajes - .acceskey = P - -receipt-not-to-cc = + .accesskey = r +receipt-not-to-cc-label = .value = Si no estoy en el Para: o Cc: del mensaje: - .acceskey = S - + .accesskey = i receipt-send-never-label = .label = No enviar nunca - receipt-send-always-label = .label = Enviar siempre - receipt-send-ask-label = .label = Preguntarme - -sender-outside-domain = +sender-outside-domain-label = .value = Si el remitente no está en mi dominio: - .acceskey = r - -other-cases-label = + .accesskey = t +other-cases-text-label = .value = En los demás casos: - .acceskey = E + .accesskey = a diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/system-integration.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/system-integration.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/preferences/system-integration.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/preferences/system-integration.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -4,16 +4,12 @@ system-integration-title = .title = Integración con el sistema - system-integration-dialog = .buttonlabelaccept = Definir como predet. .buttonlabelcancel = Omitir integración .buttonlabelcancel2 = Cancelar - default-client-intro = Usar { -brand-short-name } como cliente predeterminado para: - unset-default-tooltip = No es posible eliminar { -brand-short-name } como cliente predeterminado desde el propio { -brand-short-name }. Para que otra aplicación sea la predeterminada debe usar su diálogo 'Establecer como predeterminada'. - checkbox-email-label = .label = Correo-e .tooltiptext = { unset-default-tooltip } @@ -23,7 +19,9 @@ checkbox-feeds-label = .label = Canales .tooltiptext = { unset-default-tooltip } - +checkbox-calendar-label = + .label = Calendario + .tooltiptext = { unset-default-tooltip } # Note: This is the search engine name for all the different platforms. # Platforms that don't support it should be left blank. system-search-engine-name = @@ -32,11 +30,9 @@ [windows] Windows Search *[other] { "" } } - system-search-integration-label = .label = Permitir que { system-search-engine-name } busque en los mensajes .accesskey = P - check-on-startup-label = .label = Hacer siempre esta comprobación al iniciar { -brand-short-name } .accesskey = H diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/troubleshootMode.ftl thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/troubleshootMode.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/mail/messenger/troubleshootMode.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/mail/messenger/troubleshootMode.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -2,6 +2,23 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +troubleshoot-mode-window = + .title = Modo de resolución de problemas de { -brand-short-name } + .style = width: 37em; +troubleshoot-mode-description = Use el modo de resolución de problemas de { -brand-short-name } para diagnosticar problemas. Sus complementos y personalizaciones se desactivarán temporalmente. +troubleshoot-mode-description2 = Puede hacer permanentes todos o algunos de estos cambios: +troubleshoot-mode-disable-addons = + .label = Desactivar todos los complementos + .accesskey = D +troubleshoot-mode-reset-toolbars = + .label = Restablecer barras de herramientas y controles + .accesskey = R +troubleshoot-mode-change-and-restart = + .label = Hacer cambios y reiniciar + .accesskey = m +troubleshoot-mode-continue = + .label = Continuar en el modo de resolución de problemas + .accesskey = C troubleshoot-mode-quit = .label = { PLATFORM() -> diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/es-ES/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/es-ES/netwerk/necko.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/netwerk/necko.properties 2022-04-15 07:52:23.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=La cookie “%1$S” ha sido rechazada porque ya ha caducado. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=La cookie “%1$S” ha sido rechazada porque se encuentra en un contexto de sitios cruzados y su “SameSite” es “Lax” o “Strict”. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Advertencia: ’%1$S’ obsoleto, por favor use ’%2$S’ diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/es-ES/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/es-ES/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:52:23.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Cerrar vista de lectura @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Esquema de color claro aboutReader.toolbar.colorschemedark = Esquema de color oscuro aboutReader.toolbar.colorschemesepia = Esquema de color sepia +aboutReader.toolbar.colorschemeauto = Esquema de color automático diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/es-ES/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/es-ES/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/toolkit/chrome/global/narrate.properties 2022-04-15 07:52:23.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Escuchar back = Atrás start = Iniciar stop = Detener +# %S is the keyboard shortcut for the start command +start-label = Iniciar (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Detener (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Siguiente speed = Velocidad selectvoicelabel = Voz: diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/es-ES/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } fotograma + *[other] { $frames } fotogramas + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } canal + *[other] { $channels } canales + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/es-ES/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Barra de direcciones: mostrar resultados durante la composición IME experimental-features-ime-search-description = Una IME (Input Method Editor) es una herramienta que le permite escribir símbolos complejos, como los que se usan en los idiomas escritos del índico o Asia oriental, utilizando un teclado estándar. Activar este experimento mantendrá abierto el panel de la barra de direcciones, mostrando resultados de búsqueda y sugerencias, mientras se usa IME para escribir texto. Tenga en cuenta que el IME puede mostrar un panel que cubre los resultados de la barra de direcciones, por lo que se recomienda el uso de esta preferencia solo si el IME no usa este tipo de panel. +# Firefox 100 +experimental-features-firefox-100 = + .label = Cadena de agente de usuario { -brand-product-name } 100 +experimental-features-firefox-100-description = Haga que { -brand-short-name } envíe a los sitios web una cadena de agente de usuario que aparente ser { -brand-product-name } versión 100. Use esta configuración para probar si los sitios web fallarán cuando { -brand-short-name } llegue a un número de versión de tres dígitos. El lanzamiento real de { -brand-product-name } 100 está programado para mayo de 2022, ¡así que comience a probar sus sitios web desde ya! diff -Nru thunderbird-91.7.0+build2/l10n/es-ES/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/es-ES/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/es-ES/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:37:34.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/es-ES/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:52:23.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socket # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Actor IPC en espacio aislado ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/et/chat/matrix.properties thunderbird-91.8.1+build1/l10n/et/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/et/chat/matrix.properties 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/chat/matrix.properties 2022-04-15 07:52:30.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S tühistas verifitseerimise järgneva põhjusega: %2$S message.verification.done=Verifitseerimine lõpetati. +message.decryptionError=Selle sõnumi sisu polnud võimalik krüptida. Oma teiste seadmete krüptimisvõtmete hankimiseks paremklõpsa sellel sõnumil. +message.decrypting=Dekrüptimine... +message.redacted=Sõnumit muudeti. + +# Label in the message context menu +message.action.requestKey=Küsi võtmeid uuesti +message.action.redact=Muuda +message.action.report=Raporteeri sõnumist +message.action.retry=Proovi uuesti saata +message.action.cancel=Tühista sõnum + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Sõnumi "%1$S" saatmisel esines viga. diff -Nru thunderbird-91.7.0+build2/l10n/et/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/et/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/et/devtools/client/aboutdebugging.ftl 2022-03-07 21:37:39.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/devtools/client/aboutdebugging.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -63,7 +63,7 @@ about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Debugging Support # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar @@ -108,13 +108,13 @@ # USB section step by step guide about-debugging-setup-usb-step-plug-device = Connect the Android device to your computer. # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Problems connecting to the USB device? Troubleshoot # Network section of the Setup page about-debugging-setup-network = .title = Network Location # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Problems connecting via network location? Troubleshoot # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. @@ -166,11 +166,11 @@ # runtimes. about-debugging-runtime-profile-button2 = Profile performance # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Your browser configuration is not compatible with Service Workers. Learn more # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = The connected browser has an old version ({ $runtimeVersion }). The minimum supported version is ({ $minVersion }). This is an unsupported setup and may cause DevTools to fail. Please update the connected browser. Troubleshooting @@ -178,7 +178,7 @@ # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = This version of Firefox cannot debug Firefox for Android (68). We recommend installing Firefox for Android Nightly on your phone for testing. More details # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") @@ -224,6 +224,11 @@ # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Remove +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Terminate background script # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. @@ -247,6 +252,15 @@ # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = Extension ID +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Background script +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Running +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Stopped # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is diff -Nru thunderbird-91.7.0+build2/l10n/et/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/et/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/et/devtools/client/compatibility.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/devtools/client/compatibility.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -45,3 +45,11 @@ compatibility-no-issues-found = No compatibility issues found. compatibility-close-settings-button = .title = Close settings +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Compatibility issues in: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/et/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/et/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/et/devtools/client/netmonitor.properties 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/devtools/client/netmonitor.properties 2022-04-15 07:52:30.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=The string “%S” was removed from the beginning of the JSON shown below + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Query String: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL Parameters + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Request Headers: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Headers + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=name + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=value + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Body + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=payload + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Request Body: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Cancel +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Clear + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Remove item + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Back diff -Nru thunderbird-91.7.0+build2/l10n/et/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/et/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/et/devtools/client/toolbox-options.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/devtools/client/toolbox-options.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Enable remote debugging options-enable-remote-tooltip2 = .title = Turning this option on will allow to debug this browser instance remotely +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Enable custom formatters +options-enable-custom-formatters-tooltip = + .title = Turning this option on will allow sites to define custom formatters for DOM objects # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Enable Service Workers over HTTP (when toolbox is open) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/et/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/et/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/et/devtools/client/webconsole.properties 2022-03-07 21:37:39.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/devtools/client/webconsole.properties 2022-04-15 07:52:30.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=File +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Copy all Messages +webconsole.menu.copyAllMessages.accesskey=M + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Save all Messages to File +webconsole.menu.saveAllMessagesFile.accesskey=F + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/et/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/et/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/et/dom/chrome/dom/dom.properties 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/dom/chrome/dom/dom.properties 2022-04-15 07:52:31.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Palun sisesta URL. FormValidationInvalidDate=Palun sisesta korrektne kuupäev. FormValidationInvalidTime=Palun sisesta korrektne aeg. +FormValidationInvalidDateTime=Palun sisesta korrektne kuupäev ja aeg. +FormValidationInvalidDateMonth=Palun sisesta korrektne kuu. +FormValidationInvalidDateWeek=Palun sisesta korrektne nädal. FormValidationPatternMismatch=Palun järgi nõutud vormingut. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Palun järgi nõutud vormingut: %S. diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/et/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/et/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:37:39.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:52:30.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/aboutDialog.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Mis on uut? diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/aboutImport.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/aboutImport.ftl 2022-04-15 07:52:31.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Vali kontode, aadressiraamatute, kalendrite ja muude andmete importimine: import-address-book = Aadressiraamatu faili importimine import-calendar = Kalendri faili importimine +export-profile = Ekspordi ## Buttons button-cancel = Loobu button-back = Tagasi button-continue = Jätka +button-export = Ekspordi ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Importimine rakendusest { $app } @@ -26,17 +33,52 @@ profile-file-picker-dir = Vali profiilikaust profile-file-picker-zip = Vali ZIP-fail (väiksem kui 2GiB) items-pane-title = Imporditava valimine -items-pane-desc = Imporditakse +items-pane-source = Allika asukoht: items-pane-checkbox-accounts = kontod ja sätted items-pane-checkbox-address-books = aadressiraamatud items-pane-checkbox-calendars = kalendrid items-pane-checkbox-mail-messages = e-post +## Import from address book file steps + +import-from-addr-book-file-desc = Vali imporditava faili tüüp: +addr-book-csv-file = Koma või tabeldusmärgiga eraldatud fail (.csv, .tsv) +addr-book-ldif-file = LDIF-fail (.ldif) +addr-book-vcard-file = vCardi fail (.vcf, .vcard) +addr-book-sqlite-file = SQLite'i andmebaasifail (.sqlite) +addr-book-mab-file = Morki andmebaas (.mab) +addr-book-file-picker = Vali aadressiraamatu fail +addr-book-csv-field-map-title = Väljade nimede sobitamine +addr-book-csv-field-map-desc = Vali allikale vastavad aadressiraamatu väljad. Eemalda linnuke väljadelt, mida sa ei soovi importida. +addr-book-directories-pane-title = Vali kaust, kuhu soovid importida: +addr-book-directories-pane-source = Lähtefail: +addr-book-import-into-new-directory = Loo uus kaust + ## Import dialog progress-pane-title = Importimine +progress-pane-importing = Importimine +progress-pane-exporting = Eksportimine +progress-pane-finished-desc = Lõpetatud. progress-pane-restart-desc = Importimise lõpetamiseks taaskäivita. error-pane-title = Viga error-message-zip-file-too-big = Valitud ZIP-fail on suurem kui 2GiB. Palun paki see esmalt lahti ja impordi selle asemel lahtipakitud kaustast. error-message-extract-zip-file-failed = ZIP-faili lahtipakkimine ebaõnnestus. Paki see käsitsi lahti ja impordi selle asemel lahtipakitud kaustast. error-message-failed = Importimine ebaõnnestus ootamatult, rohkem infot võib olla saadaval veakonsoolis. +error-export-failed = Eksportimine ebaõnnestus ootamatult, rohkem infot võib olla saadaval veakonsoolis. + +## element + +csv-first-row-contains-headers = Esimene rida sisaldab väljade nimesid +csv-source-field = Allika väli +csv-source-first-record = Esimene kirje +csv-source-second-record = Teine kirje +csv-target-field = Aadressiraamatu väli + +## Export tab + +export-profile-desc = Ekspordi e-posti kontod, kirjad, aadressiraamatud ja sätted ZIP-faili. Vajadusel saad profiili taastamiseks ZIP-faili importida. +export-profile-desc2 = Kui sinu praegune profiil on suurem kui 2GiB, siis soovitame sul selle ise varundada. +export-open-profile-folder = Ava profiili kaust +export-file-picker = Ekspordi ZIP-faili +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -4,6 +4,7 @@ carddav-window = .title = Uus CardDAVi aadressiraamat +carddav-window-title = Uus CardDAVi aadressiraamat carddav-dialog = .buttonlabelaccept = Jätka .buttonaccesskeyaccept = J diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -132,8 +132,8 @@ about-addressbook-details-home-address-header = Kodune aadress about-addressbook-details-work-address-header = Tööaadress about-addressbook-details-other-info-header = Muu info -about-addressbook-prompt-to-save-title = Kas salvestada muudatused? -about-addressbook-prompt-to-save = Kas soovid oma muudatused salvestada? +about-addressbook-unsaved-changes-prompt-title = Salvestamata muudatused +about-addressbook-unsaved-changes-prompt = Kas soovid enne redigeerimisvaatest väljumist muudatused salvestada? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:52:31.000000000 +0000 @@ -84,6 +84,13 @@ .tooltiptext = Kuva manuste paneel ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Peida manuste paneel ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } manus + [one] { $count } manus + *[other] { $count } manust + } attachment-area-show = .title = Kuva manuste paneel ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -239,8 +246,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Eemalda teksti stiilid -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Laaditi üles tundmatule Filelinki kontole. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } - Filelinki manus +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = Fail { $filename } lisati teenuse Filelink lingina. Selle saab alla laadida allolevalt lingilt. # Template @@ -253,22 +273,27 @@ *[other] Linkisin selle kirjaga { $count } faili: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Rohkem teavet teenuse { $lastLink } kohta. - *[other] Rohkem teavet teenuste { $firstLinks } ja { $lastLink } kohta. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Rohkem teavet teenusepakkuja { $link } kohta. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Rohkem teavet teenuste { $firstLinks } ja { $lastLink } kohta. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Parooliga kaitstud link # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = Teenus CloudFile: +cloud-file-template-service-name = Filelinki teenus: cloud-file-template-size = Suurus: cloud-file-template-link = Link: cloud-file-template-password-protected-link = Parooliga kaitstud link: @@ -292,3 +317,9 @@ cloud-file-rename-error-with-custom-message-title = Faili { $filename } ümbernimetamine teenuses { $provider } ebaõnnestus # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = Teenus { $provider } ei toeta juba üles laaditud failide ümbernimetamist. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Filelinki manuse viga +cloud-file-attachment-error = Filelinki lisatud manust { $filename } polnud võimalik uuendada, sest selle kohalik koopia on minema liigutatud või kustutatud. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Filelinki konto viga +cloud-file-account-error = Filelinki lisatud manust { $filename } polnud võimalik uuendada, sest Filelinki konto on kustutatud. diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/messenger.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/messenger.ftl 2022-04-15 07:52:31.000000000 +0000 @@ -189,3 +189,62 @@ .title = Lülitu sätete kaardile spaces-toolbar-button-collapse = .title = Ahenda rakenduskaartide tööriistariba +spaces-toolbar-button-reveal = + .title = Kuva rakenduskaartide tööriistariba +spaces-context-new-tab-item = + .label = Ava uuel kaardil +spaces-context-new-window-item = + .label = Ava uues aknas +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Lülitu kaardile { $tabName } +settings-context-open-settings-item = + .label = Ava sätted +settings-context-open-account-settings-item = + .label = Ava kontode sätted +settings-context-open-addons-item = + .label = Ava lisad ja teemad + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Ava rakenduskaartide menüü +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [one] Üks lugemata kiri + *[other] { $count } lugemata kirja + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Kohanda... +spaces-customize-panel-title = Rakenduskaartide menüü sätted +spaces-customize-background-color = Taustavärv +spaces-customize-icon-color = Nupu värv +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Valitud nupu taustavärv +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Valitud nupu värv +spaces-customize-button-restore = Taasta vaikeväärtused + .accesskey = T +spaces-customize-button-save = Valmis + .accesskey = V diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/keyWizard.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/keyWizard.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/keyWizard.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/keyWizard.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -71,6 +71,8 @@ openpgp-keygen-ongoing = Võtme genereerimine juba käib! openpgp-keygen-error-core = OpenPGP põhiteenust pole võimalik käivitada openpgp-keygen-error-failed = OpenPGP võtme genereerimine ebaõnnestus ootamatult +# $identity (String) - the newly generate OpenPGP Key +openpgp-keygen-error-revocation = OpenPGP võtme loomine õnnestus, kuid tühistusserdi hankimine võtmele { $key } ebaõnnestus openpgp-keygen-abort-title = Kas katkestada võtme genereerimine? openpgp-keygen-abort = OpenPGP võtme genereerimine on praegu pooleli. Kas soovid kindlasti selle katkestada? # $identity (String) - the name and email address of the currently selected identity diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/msgReadStatus.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/msgReadStatus.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/msgReadStatus.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/msgReadStatus.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -28,3 +28,35 @@ openpgp-sig-uncertain-not-accepted = See kiri sisaldab digiallkirja, kuid sa pole veel otsustanud, et kas seda allkirjastaja võtit tunnustada või mitte. openpgp-sig-invalid-rejected = See kiri sisaldab digiallkirja, kuid oled otsustanud varasemalt selle allkirjastaja võtme tagasi lükata. openpgp-sig-invalid-technical-problem = See kiri sisaldab digiallkirja, kuid tuvastati tehniline viga. Kiri on kas rikutud või on seda keegi teine muutnud. +openpgp-sig-valid-unverified = See kiri sisaldab korrektset digiallkirja võtmelt, mida oled tunnustanud. Siiski pole sa veel kinnitanud, et võti tõesti kuulub saatjale. +openpgp-sig-valid-verified = See kiri sisaldab kinnitatud võtmest pärinevat korrektset digiallkirja. +openpgp-sig-valid-own-key = See kiri sisaldab sinu isiklikust võtmest pärinevat korrektset digiallkirja. +openpgp-sig-key-id = Allkirjastaja võtme ID: { $key } +openpgp-sig-key-id-with-subkey-id = Allkirjastaja võtme ID: { $key } (alamvõtme ID: { $subkey }) +openpgp-enc-key-id = Sinu dekrüptimisvõtme ID: { $key } +openpgp-enc-key-with-subkey-id = Sinu dekrüptimisvõtme ID: { $key } (alamvõtme ID: { $subkey }) +openpgp-enc-none = Kiri pole krüptitud +openpgp-enc-none-label = Kirja pole enne selle saatmist krüptitud. Selle saatmise ajal võisid seda lugeda teised inimesed. +openpgp-enc-invalid-label = Kirja pole võimalik dekrüptida +openpgp-enc-invalid = See kiri krüptiti enne saatmist, kuid paraku pole seda võimalik dekrüptida. +openpgp-enc-clueless = Antud krüptitud kirjaga esinesid tundmatud probleemid. +openpgp-enc-valid-label = Kiri on krüptitud +openpgp-enc-valid = Kiri krüptiti enne selle sulle saatmist. Krüptimine tagab, et kirja loeks ainult need, kellele see mõeldud on. +openpgp-unknown-key-id = Tundmatu võti +openpgp-other-enc-additional-key-ids = Lisaks on kiri krüptitud ka järgmiste võtmete omanikele: +openpgp-other-enc-all-key-ids = Kiri on krüptitud järgmiste võtmete omanikele: +openpgp-message-header-encrypted-ok-icon = + .alt = Dekrüptimine õnnestus +openpgp-message-header-encrypted-notok-icon = + .alt = Dekrüptimine ebaõnnestus +openpgp-message-header-signed-ok-icon = + .alt = Hea allkiri +# Mismatch icon is used for notok state as well +openpgp-message-header-signed-mismatch-icon = + .alt = Halb allkiri +openpgp-message-header-signed-unknown-icon = + .alt = Tundmatu allkirja olek +openpgp-message-header-signed-verified-icon = + .alt = Kontrollitud allkiri +openpgp-message-header-signed-unverified-icon = + .alt = Kontrollimata allkiri diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,27 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +openpgp-one-recipient-status-title = + .title = OpenPGP kirja turvalisus +openpgp-one-recipient-status-status = + .label = Olek +openpgp-one-recipient-status-key-id = + .label = Võtme ID +openpgp-one-recipient-status-created-date = + .label = Loodud +openpgp-one-recipient-status-expires-date = + .label = Aegub +openpgp-one-recipient-status-open-details = + .label = Ava üksikasjad ja muuda tunnustatust… +openpgp-one-recipient-status-discover = + .label = Avasta uus või uuendatud võti +openpgp-one-recipient-status-instruction1 = Otspunktkrüptitud kirja saatmiseks pead hankima selle saaja avaliku OpenPGP võtme ning selle tunnustama. +openpgp-one-recipient-status-instruction2 = Nende avalike võtmete saamiseks impordi need nende sulle saadetud kirjadest, mis võtmeid sisaldavad. Teise võimalusena võid proovida neid võtmeid leida avalike võtmete kataloogist. +openpgp-key-own = Tunnustatud (isiklik võti) +openpgp-key-secret-not-personal = Pole kasutatav +openpgp-key-verified = Tunnustatud (kontrollitud) +openpgp-key-unverified = Tunnustatud (kontrollimata) +openpgp-key-undecided = Pole tunnustatud (otsustamata) +openpgp-key-rejected = Pole tunnustatud (tagasi lükatud) +openpgp-key-expired = Aegunud +openpgp-intro = Saadaolevad avalikud võtmed võtme { $key } jaoks diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/openpgp-frontend.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/openpgp-frontend.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/openpgp-frontend.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/openpgp-frontend.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,48 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +openpgp-manage-keys-openpgp-cmd = + .label = OpenPGP võtmehaldur + .accesskey = O +openpgp-ctx-decrypt-open = + .label = Dekrüpti ja ava + .accesskey = D +openpgp-ctx-decrypt-save = + .label = Dekrüpti ja salvesta kui… + .accesskey = e +openpgp-ctx-import-key = + .label = Impordi OpenPGP võti + .accesskey = I +openpgp-ctx-verify-att = + .label = Kontrolli allkirja + .accesskey = K +openpgp-has-sender-key = See kiri sisaldab väidetavalt saatja OpenPGP avalikku võtit. +openpgp-be-careful-new-key = Hoiatus: see uus OpenPGP võti selles kirjas erineb avalikust võtmest, mida sa oled varasemalt e-posti aadressi { $email } jaoks tunnustanud. +openpgp-import-sender-key = + .label = Impordi… +openpgp-search-keys-openpgp = + .label = Avasta OpenPGP võti +openpgp-missing-signature-key = See kiri allkirjastati võtmega, mida sul veel pole. +openpgp-search-signature-key = + .label = Avasta… +# Don't translate the terms "OpenPGP" and "MS-Exchange" +openpgp-broken-exchange-opened = See on OpenPGP kiri, mille MS-Exchange ilmselt rikkus ja seda ei saa parandada, sest see avati kohalikust failist. Kopeeri see kiri kirjade kausta, et proovida automaatset parandamist. +openpgp-broken-exchange-info = See on OpenPGP kiri, mille MS-Exchange ilmselt rikkus. Kui kirja sisu pole kuvatud ootuspäraselt, siis võid proovida automaatset parandamist. +openpgp-broken-exchange-repair = + .label = Paranda kiri +openpgp-broken-exchange-wait = Palun oota… +openpgp-cannot-decrypt-because-mdc = + See on krüptitud kiri, mis sisaldab vana ja haavatavat mehhanismi. + Seda võidi teel olles muuta, eesmärgiga varastada selle sisu. + Selle ohu vältimiseks sisu ei kuvata. +openpgp-cannot-decrypt-because-missing-key = Kirja dekrüptimiseks vajalik salajane võti pole saadaval. +openpgp-partially-signed = + Ainult osa sellest kirjast allkirjastati OpenPGP abil. + Kontrollimise nupul vajutamisel peidetakse kaitsmata osad ja kuvatakse digiallkirja olekut. +openpgp-partially-encrypted = + Ainult osa sellest kirjast krüptiti OpenPGP abil. + Juba loetavaid osi sellest kirjast ei krüptitud. + Dekrüptimise nupul klõpsamisel kuvatakse krüptitud osade sisu. +openpgp-reminder-partial-display = Meeldetuletus: allolev kiri on ainult osa algsest kirjast. +openpgp-partial-verify-button = Kontrolli +openpgp-partial-decrypt-button = Dekrüpti diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/openpgp.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/openpgp.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/openpgp/openpgp.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/openpgp/openpgp.ftl 2022-04-15 07:52:31.000000000 +0000 @@ -1,13 +1,638 @@ - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +e2e-intro-description = Krüptitud või digiallkirjastatud kirjade saatmiseks pead seadistama krüptimistehnoloogia, kas OpenPGP või S/MIME. +e2e-intro-description-more = OpenPGP lubamiseks vali oma isiklik võti või isiklik sert, et lubada S/MIME kasutamine. Isikliku võtme või serdi kasutamiseks pead omama ka vastavat salajast võtit. +e2e-advanced-section = Täpsemad sätted +e2e-attach-key = + .label = OpenPGP allkirja lisamisel kaasatakse ka avalik võti + .accesskey = O +e2e-encrypt-subject = + .label = OpenPGP kirjade pealkirjad krüptitakse + .accesskey = G +e2e-encrypt-drafts = + .label = Mustandid salvestatakse krüptitult + .accesskey = M +openpgp-key-user-id-label = Konto / Kasutaja ID +openpgp-keygen-title-label = + .title = OpenPGP võtme loomine +openpgp-cancel-key = + .label = Loobu + .tooltiptext = Loobu võtme genereerimisest +openpgp-key-gen-expiry-title = + .label = Võtme kehtivusaeg +openpgp-key-gen-expire-label = Võti aegub +openpgp-key-gen-days-label = + .label = päeva pärast +openpgp-key-gen-months-label = + .label = kuu pärast +openpgp-key-gen-years-label = + .label = aasta pärast +openpgp-key-gen-no-expiry-label = + .label = Võti ei aegu +openpgp-key-gen-key-size-label = Võtme suurus +openpgp-key-gen-console-label = Võtme genereerimine +openpgp-key-gen-key-type-label = Võtme tüüp +openpgp-key-gen-key-type-rsa = + .label = RSA +openpgp-key-gen-key-type-ecc = + .label = ECC (elliptiline kõver) +openpgp-generate-key = + .label = Genereeri võti + .tooltiptext = Loob uue OpenPGP ühilduva võtme krüptimiseks ja/või allkirjastamiseks +openpgp-advanced-prefs-button-label = + .label = Edasijõudnuile... +openpgp-keygen-desc = MÄRKUS: Võtme genereerimine võib aega võtta mõned minutid. Genereerimise ajal ära sulge rakendust. Aktiivne veebilehitsemine või intensiivselt salvestusandmekandjate kasutamine võtme genereerimise ajal aitab täita juhuslikkuse kogumit ning protsessi kiirendada. Sind teavitatakse genereerimise protsessi lõppemisest. +openpgp-key-expiry-label = + .label = Aegumine +openpgp-key-id-label = + .label = Võtme ID +openpgp-cannot-change-expiry = See võti on keerulise struktuuriga, selle aegumise muutmine pole toetatud. +openpgp-key-man-title = + .title = OpenPGP võtmehaldur +openpgp-key-man-generate = + .label = Uus võtmepaar + .accesskey = U +openpgp-key-man-gen-revoke = + .label = Tühistussert + .accesskey = T +openpgp-key-man-ctx-gen-revoke-label = + .label = Loo ja salvesta tühistussert +openpgp-key-man-file-menu = + .label = Fail + .accesskey = F +openpgp-key-man-edit-menu = + .label = Redigeerimine + .accesskey = R +openpgp-key-man-view-menu = + .label = Vaade + .accesskey = V +openpgp-key-man-generate-menu = + .label = Genereerimine + .accesskey = G +openpgp-key-man-keyserver-menu = + .label = Võtmeserver + .accesskey = V +openpgp-key-man-import-public-from-file = + .label = Impordi avalikke võtmeid failist + .accesskey = f +openpgp-key-man-import-secret-from-file = + .label = Impordi privaatseid võtmeid failist +openpgp-key-man-import-sig-from-file = + .label = Impordi tühistusserte failist +openpgp-key-man-import-from-clipbrd = + .label = Impordi võtmeid vahemälust + .accesskey = v +openpgp-key-man-import-from-url = + .label = Impordi võtmed URLilt + .accesskey = U +openpgp-key-man-export-to-file = + .label = Ekspordi avalikud võtmed faili + .accesskey = E +openpgp-key-man-send-keys = + .label = Saada avalikud võtmed e-postiga + .accesskey = v +openpgp-key-man-backup-secret-keys = + .label = Varunda salajased võtmed faili + .accesskey = r +openpgp-key-man-discover-cmd = + .label = Avasta võtmeid võrgust + .accesskey = t +openpgp-key-man-discover-prompt = OpenPGP võtmete avastamiseks võrgust, võtmete serverist või kasutades WKD-protokolli, kasuta kas e-posti aadressi või võtme ID'd. +openpgp-key-man-discover-progress = Otsimine... +openpgp-key-copy-key = + .label = Kopeeri avalik võti + .accesskey = K +openpgp-key-export-key = + .label = Ekspordi avalik võti faili + .accesskey = E +openpgp-key-backup-key = + .label = Varunda salajane võti faili + .accesskey = V +openpgp-key-send-key = + .label = Saada avalik võti e-postiga + .accesskey = d +openpgp-key-man-copy-key-ids = + .label = + { $count -> + [one] Kopeeri võtme ID vahemällu + *[other] Kopeeri võtme ID'd vahemällu + } + .accesskey = o +openpgp-key-man-copy-fprs = + .label = + { $count -> + [one] Kopeeri sõrmejälg vahemällu + *[other] Kopeeri sõrmejäljed vahemällu + } + .accesskey = j +openpgp-key-man-copy-to-clipboard = + .label = + { $count -> + [one] Kopeeri avalik võti vahemällu + *[other] Kopeeri avalikud võtmed vahemällu + } + .accesskey = p +openpgp-key-man-ctx-expor-to-file-label = + .label = Ekspordi võtmed faili +openpgp-key-man-ctx-copy = + .label = Kopeeri + .accesskey = K +openpgp-key-man-ctx-copy-fprs = + .label = + { $count -> + [one] Sõrmejälg + *[other] Sõrmejäljed + } + .accesskey = S +openpgp-key-man-ctx-copy-key-ids = + .label = + { $count -> + [one] Võtme ID + *[other] Võtme ID'd + } + .accesskey = t +openpgp-key-man-ctx-copy-public-keys = + .label = + { $count -> + [one] Avalik võti + *[other] Avalikud võtmed + } + .accesskey = A +openpgp-key-man-close = + .label = Sulge +openpgp-key-man-reload = + .label = Laadi võtmete vahemälu uuesti + .accesskey = L +openpgp-key-man-change-expiry = + .label = Muuda aegumiskuupäeva + .accesskey = M +openpgp-key-man-del-key = + .label = Kustuta võtmed + .accesskey = K +openpgp-delete-key = + .label = Kustuta võti + .accesskey = u +openpgp-key-man-revoke-key = + .label = Tühista võti + .accesskey = T +openpgp-key-man-key-props = + .label = Võtme omadused + .accesskey = o +openpgp-key-man-key-more = + .label = Rohkem + .accesskey = R +openpgp-key-man-view-photo = + .label = Foto ID + .accesskey = F +openpgp-key-man-ctx-view-photo-label = + .label = Vaata foto ID'd +openpgp-key-man-show-invalid-keys = + .label = Kuva vigaseid võtmeid + .accesskey = i +openpgp-key-man-show-others-keys = + .label = Kuva võtmeid teistelt inimestelt + .accesskey = m +openpgp-key-man-user-id-label = + .label = Nimi +openpgp-key-man-fingerprint-label = + .label = Sõrmejälg +openpgp-key-man-select-all = + .label = Valige Kõik võtmed + .accesskey = V +openpgp-key-man-empty-tree-tooltip = + .label = Sisesta otsingufraas ülalolevasse kasti +openpgp-key-man-nothing-found-tooltip = + .label = Sinu otsituga sobivaid võtmeid ei leitud +openpgp-key-man-please-wait-tooltip = + .label = Palun oota, kuni võtmeid laaditakse… +openpgp-key-man-filter-label = + .placeholder = Otsi võtmeid +openpgp-key-man-select-all-key = + .key = A +openpgp-key-man-key-details-key = + .key = I +openpgp-key-details-title = + .title = Võtme omadused +openpgp-key-details-signatures-tab = + .label = Serdid +openpgp-key-details-structure-tab = + .label = Struktuur +openpgp-key-details-uid-certified-col = + .label = Kasutaja ID / Sertifitseerija +openpgp-key-details-user-id2-label = Väidetav võtme omanik +openpgp-key-details-id-label = + .label = ID +openpgp-key-details-key-type-label = Tüüp +openpgp-key-details-key-part-label = + .label = Võtme osa +openpgp-key-details-algorithm-label = + .label = Algoritm +openpgp-key-details-size-label = + .label = Suurus +openpgp-key-details-created-label = + .label = Loodud +openpgp-key-details-created-header = Loodud +openpgp-key-details-expiry-label = + .label = Aegumine +openpgp-key-details-expiry-header = Aegumine +openpgp-key-details-usage-label = + .label = Kasutus +openpgp-key-details-fingerprint-label = Sõrmejälg +openpgp-key-details-sel-action = + .label = Vali tegevus… + .accesskey = V +openpgp-key-details-also-known-label = Võtmeomaniku väidetavad alternatiivsed identiteedid: +openpgp-card-details-close-window-label = + .buttonlabelaccept = Sulge +openpgp-acceptance-label = + .label = Sinu tunnustus +openpgp-acceptance-rejected-label = + .label = Ei, lükka see võti tagasi. +openpgp-acceptance-undecided-label = + .label = Mitte praegu, võib-olla hiljem. +openpgp-acceptance-unverified-label = + .label = Jah, aga ma ei ole kontrollinud, kas see on õige võti. +openpgp-acceptance-verified-label = + .label = Jah, ma olen isiklikult kontrollinud, et sellel võtmel on õige sõrmejälg. +key-accept-personal = + Selle võtme jaoks on sul olemas nii avalik kui ka salajane osa. Sa võid kasutada seda isikliku võtmena. + Kui selle võtme andis sulle keegi teine, siis ära kasuta seda isikliku võtmena. +key-personal-warning = Kas sa lõid selle võtme ise ja kuvatud võtme omandiõigus viitab sulle? +openpgp-personal-no-label = + .label = Ei, ära kasuta seda minu isikliku võtmena. +openpgp-personal-yes-label = + .label = Jah, käsitle seda võtit minu isikliku võtmena. +openpgp-copy-cmd-label = + .label = Kopeeri + ## e2e encryption settings +# $count (Number) - the number of configured keys associated with the current identity +# $identity (String) - the email address of the currently selected identity +openpgp-description = + { $count -> + [0] Thunderbirdil pole isiklikku OpenPGP võtit identiteedile { $identity } + [one] Thunderbird leidis ühe identiteediga { $identity } seotud OpenPGP võtme + *[other] Thunderbird leidis { $count } identiteediga { $identity } seotud OpenPGP võtit + } +# $key (String) - the currently selected OpenPGP key +openpgp-selection-status-have-key = Sinu praegune seadistus kasutab võtit IDga { $key } +# $key (String) - the currently selected OpenPGP key +openpgp-selection-status-error = Praegune seadistus kasutab võtit { $key }, mis on aegunud. +openpgp-add-key-button = + .label = Lisa võti… + .accesskey = L +e2e-learn-more = Rohkem teavet +openpgp-keygen-success = OpenPGP võtme loomine õnnestus! +openpgp-keygen-import-success = OpenPGP võtmed edukalt imporditud! +openpgp-keygen-external-success = Välise GnuPG võtme ID salvestatud! + ## OpenPGP Key selection area +openpgp-radio-none = + .label = Puudub +openpgp-radio-none-desc = OpenPGPd selle identiteedi jaoks ei kasutata. +openpgp-radio-key-not-usable = See võti pole isikliku võtmena kasutatav, sest puudub salajane võti. +openpgp-radio-key-not-accepted = Selle võtme kasutamiseks pead tunnustama seda isikliku võtmena. +openpgp-radio-key-not-found = Seda võtit ei leitud. Selle kasutamiseks pead selle { -brand-short-name }i importima. +# $key (String) - the expiration date of the OpenPGP key +openpgp-radio-key-expires = Aegub: { $date } +# $key (String) - the expiration date of the OpenPGP key +openpgp-radio-key-expired = Aegus: { $date } +openpgp-key-expires-within-6-months-icon = + .title = Võti aegub vähem kui 6 kuu pärast +openpgp-key-has-expired-icon = + .title = Võti on aegunud +openpgp-key-expand-section = + .tooltiptext = Rohkem teavet +openpgp-key-revoke-title = Tühista võti +openpgp-key-edit-title = Muuda OpenPGP võtit +openpgp-key-edit-date-title = Pikenda kehtivusaega +openpgp-manager-description = Kasuta OpenPGP võtmehaldurit oma kontaktide avalike võtmete ja kõigi muude võtmete haldamiseks, mida ülal pole loetletud. +openpgp-manager-button = + .label = OpenPGP võtmehaldur + .accesskey = O +openpgp-key-remove-external = + .label = Eemalda välise võtme ID + .accesskey = E +key-external-label = Väline GnuPG võti +# Strings in keyDetailsDlg.xhtml +key-type-public = avalik võti +key-type-primary = peamine võti +key-type-subkey = alamvõti +key-type-pair = võtmepaar (salajane ja avalik võti) +key-expiry-never = mitte kunagi +key-usage-encrypt = Krüptimine +key-usage-sign = Allkirjastamine +key-usage-certify = Sertifitseerimine +key-usage-authentication = Autentimine +key-does-not-expire = Võti ei aegu +key-expired-date = Võti aegus { $keyExpiry } +key-expired-simple = Võti on aegunud +key-revoked-simple = Võti tühistati +key-do-you-accept = Kas tunnustad seda võtit digiallkirjade kontrollimiseks ja kirjade krüptimiseks? +key-accept-warning = Väldi võlts võtmete tunnustamist. Kasuta oma kontakti võtme sõrmejälje kontrollimiseks muud suhtluskanalit peale e-posti. +# Strings enigmailMsgComposeOverlay.js +cannot-use-own-key-because = Kirja saatmine pole võimalik, sest esineb probleem sinu isikliku võtmega. { $problem } +cannot-encrypt-because-missing = Otspunktkrüptitud kirja pole võimalik saata, sest järgnevate saajate võtmetega on probleeme: { $problem } +window-locked = Koostamise aken on lukus, saatmine katkestati +# Strings in mimeDecrypt.jsm +mime-decrypt-encrypted-part-attachment-label = Krüptitud kirja osa +# Strings in mimeDecrypt.jsm +mime-decrypt-encrypted-part-concealed-data = See on krüptitud kirja osa. Selle avamiseks eraldi aknas pead klõpsama manusel. +# Strings in keyserver.jsm +keyserver-error-aborted = Katkestatud +keyserver-error-unknown = Esines tundmatu viga +keyserver-error-server-error = Võtmeserver teatas veast. +keyserver-error-import-error = Allalaaditud võtme importimine ebaõnnestus. +keyserver-error-unavailable = Võtmeserver pole saadaval. +keyserver-error-security-error = Võtmeserver ei toeta krüptitud ligipääsu. +keyserver-error-certificate-error = Võtmeserveri sert ei kehti. +keyserver-error-unsupported = Võtmeserver pole toetatud. +# Strings in mimeWkdHandler.jsm +wkd-message-body-req = + Sinu e-posti teenusepakkuja töötles sinu taotluse avaliku võtme üleslaadimiseks OpenPGP veebis olevasse võtmete kataloogi. + Lõpetamiseks kinnita palun avaliku võtme avalikustamine. +wkd-message-body-process = + See kiri on seotud teie avaliku võtme veebis olevasse OpenPGP võtmete kataloogi lisamise taotluse automaatse töötlemisega. + Praegu ei ole sul vaja täiendavaid tegevusi teha. +# Strings in persistentCrypto.jsm +converter-decrypt-body-failed = + Kirja pealkirjaga { $subject } + polnud võimalik dekrüptida. + Kas soovid proovida teise parooliga või jätta selle kirja vahele? +# Strings in gpg.jsm +unknown-signing-alg = Tundmatu allkirjastamisalgoritm (ID: { $id }) +unknown-hash-alg = Tundmatu krüptograafiline räsi (ID: { $id }) +# Strings in keyUsability.jsm +expiry-key-expires-soon = + Sinu võti { $desc } aegub vähem kui { $days } päeva pärast. + Me soovitame luua uue võtmepaari ja seadistada vastavad kontod seda kasutama. +expiry-keys-expire-soon = + Sinu järgmised võtmed aeguvad vähem kui { $days } päeva pärast: { $desc } + Me soovitame luua uued võtmed ja seadistada vastavad kontod neid kasutama. +expiry-key-missing-owner-trust = + Sinu salajasel võtmel { $desc } puudub usaldusväärsus. + Me soovitame, et määrad võtme omaduste juures sektsioonis "Sinu tunnustus" väärtuseks "Jah, käsitle seda võtit minu isikliku võtmena". +expiry-keys-missing-owner-trust = + Järgmistel sinu salajastel võtmetel puudub usaldusväärsus. + { $desc } + Me soovitame, et määrad võtme omaduste juures sektsioonis "Sinu tunnustus" väärtuseks "Jah, käsitle seda võtit minu isikliku võtmena". +expiry-open-key-manager = Ava OpenPGP võtmehaldur +expiry-open-key-properties = Ava võtme omadused +# Strings filters.jsm +filter-folder-required = Sa pead valima sihtkausta. +filter-decrypt-move-warn-experimental = + Hoiatus - filtri tegevus "Dekrüpti jäädavalt" võib viia kirjade hävitamiseni. + Me soovitame tungivalt, et proovid kõigepealt filtrit "Loo dekrüptitud koopia", testid seda põhjalikult ja ainult siis alustad selle filtri kasutamist, kui oled tulemustega rahul. +filter-term-pgpencrypted-label = OpenPGPga krüptitud +filter-key-required = Sa pead valima saaja võtme. +filter-key-not-found = Krüpteerimisvõtit ‘{ $desc }’ jaoks ei leitud. +filter-warn-key-not-secret = + Hoiatus - filtri tegevus "Krüpteeri võtmega" asendab saajad. + Kui sul puudub ‘{ $desc }’ jaoks salajane võti, siis pole sul enam võimalik neid kirju lugeda. +# Strings filtersWrapper.jsm +filter-decrypt-move-label = Dekrüpti jäädavalt (OpenPGP) +filter-decrypt-copy-label = Loo dekrüpteeritud koopia (OpenPGP) +filter-encrypt-label = Krüpteeri võtmega (OpenPGP) +# Strings in enigmailKeyImportInfo.js +import-info-title = + .title = Võtmete importimine õnnestus! +import-info-bits = Bitid +import-info-created = Loodud +import-info-fpr = Sõrmejälg +import-info-details = Vaata üksikasju ja halda võtme tunnustust +import-info-no-keys = Võtmeid ei imporditud. +# Strings in enigmailKeyManager.js +import-from-clip = Kas soovid importida mõned võtmed vahemälust? +import-from-url = Laadi avalik võti alla järgnevalt URLilt: +copy-to-clipbrd-failed = Valitud võtmeid polnud võimalik vahemällu kopeerida. +copy-to-clipbrd-ok = Võtmed kopeeriti vahemällu +delete-secret-key = + HOIATUS: oled kustutamas salajast võtit! + + Kui sa kustutad oma salajase võtme, siis pole sul võimalik enam dekrüptida sellele võtmele krüptitud kirju ning sul pole võimalik seda võtit tühistada. + + Kas soovid kindlasti kustutada nii avaliku kui salajase võtme + ‘{ $userId }’? +delete-mix = + HOIATUS: oled kustutamas salajasi võtmeid! + Kui sa kustutad oma salajase võtme, siis pole sul võimalik enam dekrüptida sellele võtmele krüptitud kirju. + Kas soovid kindlasti kustutada nii valitud salajased kui avalikud võtmed? +delete-pub-key = Kas soovid kustutada avaliku võtme ‘{ $userId }’? +delete-selected-pub-key = Kas soovid kustutada avalikud võtmed? +refresh-all-question = Sa ei valinud ühtki võtit. Kas soovid uuendada KÕIKI võtmeid? +key-man-button-export-sec-key = Ekspordi &salajased võtmed +key-man-button-export-pub-key = Ekspordi &ainult avalikud võtmed +key-man-button-refresh-all = &Uuenda kõik võtmed +key-man-loading-keys = Võtmete laadimine, palun oota… +ascii-armor-file = ASCII-soomustatud failid (*.asc) +no-key-selected = Valitud tegevuse tegemiseks peaksid valima vähemalt ühe võtme +export-to-file = Ekspordi avalik võti faili +export-keypair-to-file = Ekspordi salajane ja avalik võti faili +export-secret-key = Kas soovid lisada salajase võtme salvestatud OpenPGP võtmefaili? +save-keys-ok = Võtmed salvestati edukalt +save-keys-failed = Võtmete salvestamine ebaõnnestus +default-pub-key-filename = Eksporditud-avalikud-võtmed +default-pub-sec-key-filename = Salajaste-võtmete-varukoopia +refresh-key-warn = Hoiatus: sõltuvalt võtmete arvust ja ühenduse kiirusest võib kõigi võtmete uuendamine olla üsna pikk protsess! +preview-failed = Avaliku võtme faili pole võimalik lugeda. +general-error = Viga: { $reason } +dlg-button-delete = &Kustuta + ## Account settings export output +openpgp-export-public-success = Avalik võti edukalt eksporditud! +openpgp-export-public-fail = Valitud avalikku võtit pole võimalik eksportida! +openpgp-export-secret-success = Salajane võti edukalt eksporditud! +openpgp-export-secret-fail = Valitud salajast võtit pole võimalik eksportida! +# Strings in keyObj.jsm +key-ring-pub-key-revoked = Võti { $userId } (võtme ID { $keyId }) on tühistatud. +key-ring-pub-key-expired = Võti { $userId } (võtme ID { $keyId }) on aegunud. +key-ring-no-secret-key = Sinu võtmerõngal ei näi olevat salajast võtit võtme { $userId } (võtme ID { $keyId }) jaoks; seda võtit pole võimalik allkirjastamiseks kasutada. +key-ring-pub-key-not-for-signing = Võtit { $userId } (võtme ID { $keyId }) pole võimalik allkirjastamiseks kasutada. +key-ring-pub-key-not-for-encryption = Võtit { $userId } (võtme ID { $keyId }) pole võimalik krüptimiseks kasutada. +key-ring-sign-sub-keys-revoked = Kõik võtme { $userId } (võtme ID { $keyId }) allkirjastamist võimaldavad alamvõtmed on tühistatud. +key-ring-sign-sub-keys-expired = Kõik võtme { $userId } (võtme ID { $keyId }) allkirjastamise alamvõtmed on aegunud. +key-ring-enc-sub-keys-revoked = Kõik võtme { $userId } (võtme ID { $keyId }) krüptimise alamvõtmed on tühistatud. +key-ring-enc-sub-keys-expired = Kõik võtme { $userId } (võtme ID { $keyId }) krüptimise alamvõtmed on aegunud. +# Strings in gnupg-keylist.jsm +keyring-photo = Pilt +user-att-photo = Kasutaja atribuut (JPEG-pilt) +# Strings in key.jsm +already-revoked = See võti on juba tühistatud. +# $identity (String) - the id and associated user identity of the key being revoked +revoke-key-question = + Oled tühistamas võtit ‘{ $identity }’. + Sul pole võimalik enam selle võtmega allkirjastada ja pärast levitamist ei saa teised enam selle võtmega krüptida. Saad seda endiselt kasutada, et dekrüptida vanu kirju. + Kas soovid jätkata? +# $keyId (String) - the id of the key being revoked +revoke-key-not-present = + Sul pole võtit (ux{ $keyId }), mis vastaks sellele tühistamise serdile. + Kui oled kaotanud oma võtme, siis pead selle importima (näiteks võtmete serverist) enne tühistusserdi importimist! +# $keyId (String) - the id of the key being revoked +revoke-key-already-revoked = Võti 0x{ $keyId } on juba tühistatud. +key-man-button-revoke-key = &Tühista võti +openpgp-key-revoke-success = Võti tühistati edukalt. +after-revoke-info = + Võti on tühistatud. + Jaga seda avalikku võtit uuesti, saates see e-postiga või laadides üles võtmete serverisse, et anda teistele teada selle tühistamisest. + Kohe, kui teiste poolt kasutatav tarkvara saab teada võtme tühistamisest, lõpetab see sinu vana võtme kasutamise. + Kui oled kasutamas uut võtit sama e-posti aadressi jaoks ja lisad selle avaliku võtme oma saadetavatele kirjadele, siis lisatakse automaatselt ka info vana võtme tühistamise kohta. +# Strings in keyRing.jsm & decryption.jsm +key-man-button-import = &Impordi +delete-key-title = Kustuta OpenPGP võti +delete-external-key-title = Eemalda väline GnuPG võti +delete-external-key-description = Kas soovid eemaldada selle välise GnuPG võtme ID? +key-in-use-title = OpenPGP võti on praegu kasutusel +delete-key-in-use-description = Pole võimalik jätkata! Võti, mille valisid kustutamiseks, on praegu selle identiteedi poolt kasutuses. Vali teine võti või vali mitte ükski ja proovi siis uuesti. +revoke-key-in-use-description = Pole võimalik jätkata! Võti, mille valisid tühistamiseks, on praegu selle identiteedi poolt kasutuses. Vali teine võti või vali mitte ükski ja proovi siis uuesti. +# Strings used in errorHandling.jsm +key-error-key-spec-not-found = E-posti aadressi ‘{ $keySpec }’ pole võimalik sobitada ühegi võtmega sinu võtmerõngal. +key-error-key-id-not-found = Seadistatud võtit ‘{ $keySpec }’ pole võimalik sinu võtmerõngalt leida. +key-error-not-accepted-as-personal = Sa pole kinnitanud, et võti IDga ‘{ $keySpec }’ on sinu isiklik võti. +# Strings used in enigmailKeyManager.js & windows.jsm +need-online = Valitud funktsionaalsus pole võrguta režiimis saadaval. Palun ühendu võrku ja proovi siis uuesti. +# Strings used in keyRing.jsm & keyLookupHelper.jsm +no-key-found = Me ei leidnud otsingule vastavat võtit. +# Strings used in keyRing.jsm & GnuPGCryptoAPI.jsm +fail-key-extract = Viga - võtme eksportimise käsk ebaõnnestus +# Strings used in keyRing.jsm +fail-cancel = Viga - võtme vastuvõtmine katkestati kasutaja poolt +not-first-block = Viga - esimene OpenPGP plokk pole avaliku võtme plokk +import-key-confirm = Kas importida kirjas sisalduvad avalikud võtmed? +fail-key-import = Viga - võtme importimine ebaõnnestus +file-write-failed = Faili { $output } kirjutamine ebaõnnestus +no-pgp-block = Viga - kehtivat soomustatud OpenPGP andmete plokki ei leitud +confirm-permissive-import = Importimine ebaõnnestus. Imporditav võti võib olla rikutud või kasutab tundmatuid atribuute. Kas soovid proovida importida korrektsed osad? See võib kaasa tuua mittetäielike ja kasutuskõlbmatute võtmete importimise. +# Strings used in trust.jsm +key-valid-unknown = tundmatu +key-valid-invalid = vigane +key-valid-disabled = keelatud +key-valid-revoked = tühistatud +key-valid-expired = aegunud +key-trust-untrusted = ebausaldusväärne +key-trust-marginal = marginaalne +key-trust-full = usaldatud +key-trust-ultimate = ülim +key-trust-group = (grupp) +# Strings used in commonWorkflows.js +import-key-file = Impordi OpenPGP võtmefail +import-rev-file = Impordi OpenPGP tühistusfail +gnupg-file = GnuPG failid +import-keys-failed = Võtmete importimine ebaõnnestus +passphrase-prompt = Palun sisesta järgmise võtme avamiseks parool: { $key } +file-to-big-to-import = Fail on liiga suur. Palun ära impordi suurt arvu võtmeid korraga. +# Strings used in enigmailKeygen.js +save-revoke-cert-as = Loo ja salvesta tühistussert +revoke-cert-ok = Tühistussert on edukalt loodud. Sa võid seda kasutada, et tunnistada oma avalik võti kehtetuks, nt juhul kui oled kaotanud oma salajase võtme. +revoke-cert-failed = Tühistusserti polnud võimalik luua. +gen-going = Võtme genereerimine juba käib! +keygen-missing-user-name = Valitud konto/identiteedi jaoks pole nime määratud. Palun sisesta konto sätetes väärtus väljale “Sinu nimi”. +expiry-too-short = Võti peab kehtima vähemalt ühe päeva. +expiry-too-long = Üle 100 aasta kehtivat võtit pole võimalik luua. +key-confirm = Kas genereerida identiteedi ‘{ $id }’ jaoks avalik ja salajane võti? +key-man-button-generate-key = &Genereeri võti +key-abort = Kas katkestada võtme genereerimine? +key-man-button-generate-key-abort = &Katkesta võtme genereerimine +key-man-button-generate-key-continue = &Jätka võtme genereerimist + # Strings used in enigmailMessengerOverlay.js +failed-decrypt = Viga - dekrüptimine ebaõnnestus +fix-broken-exchange-msg-failed = Seda kirja pole võimalik parandada. +attachment-no-match-from-signature = Allkirjafaili ‘{ $attachment }’ polnud võimalik manusega sobitada +attachment-no-match-to-signature = Manust ‘{ $attachment }’ polnud võimalik allkirjafailiga sobitada +signature-verified-ok = Manuse { $attachment } allkiri kinnitati edukalt +signature-verify-failed = Manuse { $attachment } allkirja polnud võimalik kontrollida +decrypt-ok-no-sig = + Hoiatus + Dekrüptimine oli edukas, aga allkirja polnud võimalik õigesti kontrollida +msg-ovl-button-cont-anyway = &Jätka ikkagi +enig-content-note = *Selle kirja manuseid pole allkirjastatud ega krüptitud* +# Strings used in enigmailMsgComposeOverlay.js +msg-compose-button-send = &Saada kiri +msg-compose-details-button-label = Üksikasjad… +msg-compose-details-button-access-key = k +send-aborted = Saatmisoperatsioon katkestati. +key-not-trusted = Võtme ‘{ $key }’ usaldus pole piisav +key-not-found = Võtit ‘{ $key }’ ei leitud +key-revoked = Võti ‘{ $key }’ tühstati +key-expired = Võti ‘{ $key }’ aegus +msg-compose-internal-error = Esines sisemine viga. +keys-to-export = Vali sisestatavad OpenPGP võtmed +msg-compose-partially-encrypted-inlinePGP = + Kiri, millele vastad, sisaldas nii krüptimata kui krüptitud osi. Kui saatjal polnud võimalik mõndasid kirja osi algselt dekrüptida, siis sa võid lekitada konfidentsiaalset infot, mida saatja ise algselt dekrüptida ei saanud. + Palun kaalu kõigi tsiteeritud osade eemaldamist sellest vastusest saatjale. +msg-compose-cannot-save-draft = Viga mustandi salvestamisel +msg-compose-partially-encrypted-short = Hoidu tundliku info lekitamisest - osaliselt krüptitud kiri. +quoted-printable-warn = + Oled kirjade saatmiseks lubanud kodeeringu ‘tsiteeritud-prinditav’. See võib põhjustada sinu kirja vale dekrüptimist ja/või kontrollimist. + Kas soovid ‘tsiteeritud-prinditav’ kirjade saatmise praegu välja lülitada? +minimal-line-wrapping = + Sa oled määranud reamurdmise { $width } märgi peale. Korrektse krüptimise ja/või allkirjastamise jaoks peab see väärtus olema vähemalt 68. + Kas soovid reamurdmise muuta 68 märgi peale? +sending-news = + Krüptitud saatmise toiming katkestati. + Seda kirja polnud võimalik krüptida, sest sellel on uudistegrupi adressaate. Palun proovi kirja uuesti saata ilma krüptimiseta. +send-to-news-warning = + Hoiatus: oled saatmas krüptitud kirja uudistegrupile. + Seda ei soovitata teha, sest see on mõttekas ainult siis, kui kõik grupi liikmed saavad kirja dekrüptida (st, et kiri peaks olema krüptitud kõigi grupiliikmete võtmetega). Palun saada see kiri ainult siis, kui tead, mida teed. + Kas jätkata? +save-attachment-header = Salvesta dekrüptitud manus +no-temp-dir = + Ajutist kausta, kuhu kirjutada, ei leitud + Palun määra keskkonnamuutuja TEMP +possibly-pgp-mime = Võimalik PGP/MIME krüptitud või allkirjastatud kiri, kontrollimiseks kasuta ‘dekrüptimise/kontrollimise’ funktsionaalsust +cannot-send-sig-because-no-own-key = Seda kirja pole võimalik digitaalselt allkirjastada, sest sa pole veel seadistanud otspunktkrüptimist võtme <{ $key }> jaoks +cannot-send-enc-because-no-own-key = Seda kirja pole võimalik krüptitult saata, sest sa pole veel seadistanud otspunktkrüptimist võtme <{ $key }> jaoks +compose-menu-attach-key = + .label = Lisa minu avalik võti + .accesskey = L +compose-menu-encrypt-subject = + .label = Teema krüptimine + .accesskey = T +# Strings used in decryption.jsm +do-import-multiple = + Kas importida järgnevad võtmed? + { $key } +do-import-one = Kas importida { $name } ({ $id })? +cant-import = Viga avaliku võtme importimisel +unverified-reply = Tõenäoliselt muudeti taandega kirja osa (vastust) +key-in-message-body = Kirja sisust leiti võti. Importimiseks klõpsa ‘Impordi võti’ +sig-mismatch = Viga - allkirja mittevastavus +invalid-email = Viga - mittekorrektsed e-posti aadressid +attachment-pgp-key = + Avatav manus ‘{ $name }’ tundub olevat OpenPGP võtmefail. + Võtmete importimiseks klõpsa ‘Impordi’ või faili sisu avamiseks brauseris klõpsa ‘Vaata’ +dlg-button-view = &Vaata +# Strings used in enigmailMsgHdrViewOverlay.js +decrypted-msg-with-format-error = Dekrüptitud kiri (taastatud katkise PGP e-kirja formaat, mille põhjustas tõenäoliselt vana Exhange'i server, nii et tulemus ei pruugi olla lugemiseks kõlblik) +# Strings used in encryption.jsm +not-required = Viga - krüptimine pole nõutud +# Strings used in windows.jsm +no-photo-available = Pilt pole saadaval +error-photo-path-not-readable = Pildi asukoht ‘{ $photo }’ pole loetav +debug-log-title = OpenPGP silumislogi +# Strings used in dialog.jsm +repeat-prefix = See hoiatus kordub { $count } +repeat-suffix-singular = kord veel. +repeat-suffix-plural = korda veel. +no-repeat = Seda hoiatust enam ei kuvata. +dlg-keep-setting = Vastus peetakse meeles ja rohkem enam ei küsita +dlg-button-ok = &Sobib +dlg-button-close = S&ulge +dlg-button-cancel = &Loobu +dlg-no-prompt = Seda akent rohkem ei näidata +enig-prompt = OpenPGP dialoog +enig-confirm = OpenPGP kinnitus +enig-alert = OpenPGP hoiatus +enig-info = OpenPGP teave +# Strings used in persistentCrypto.jsm +dlg-button-retry = &Proovi uuesti +dlg-button-skip = &Jäta vahele +# Strings used in enigmailMsgBox.js +enig-alert-title = + .title = OpenPGP hoiatus diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/add-finger.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/add-finger.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,14 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +otr-add-finger = + .title = OTR-võtme sõrmejälje lisamine +otr-add-finger-title = OTR-võtme sõrmejälje lisamine +# Variables: +# $name (String) - name of a chat contact person +# Do not translate 'OTR' (name of an encryption protocol) +otr-add-finger-description = Sisesta kontakti { $name } OTR-võtme sõrmejälg. +otr-add-finger-fingerprint = Sõrmejälg: +otr-add-finger-tooltip-error = Sisestati vigane tähemärk. Ainult tähed ABCDEF ja numbrid on lubatud. +otr-add-finger-input = + .placeholder = 40 tähemärgi pikkune OTR-võtme sõrmejälg diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/am-im-otr.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/am-im-otr.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/am-im-otr.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/am-im-otr.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,26 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +account-encryption = + .label = Otspunktkrüptimine +account-otr-label = Salvestusväline sõnumside (OTR) +account-otr-description = { -brand-short-name } toetab üks-ühele vestluste täielikku krüptimist. See takistab kolmandatel isikutel vestlust pealt kuulamast. Otspunktkrüptimist saab kasutada ainult siis, kui teine isik kasutab samuti OTRi toetavat tarkvara. +account-otr-description2 = { -brand-short-name } toetab OTRil põhinevat üks-ühele vestluste täielikku krüptimist. See takistab kolmandatel isikutel vestlust pealt kuulamast. Otspunktkrüptimist saab kasutada ainult siis, kui teine isik kasutab samuti OTRi toetavat tarkvara. +otr-encryption-title = Kontrollitud krüptimine +otr-encryption-caption = Et teised saaksid OTR-vestlustes sinu identiteeti kinnitada, jaga oma OTRi sõrmejälge, kasutades mingit teist sidekanalit. +otr-fingerprint-label = Sinu sõrmejälg: +view-fingerprint-button = + .label = Halda kontaktide sõrmejälgi + .accesskey = H +otr-settings-title = OTRi sätted +otr-log = + .label = OTRiga krüptitud sõnumid kaasatakse vestluste logidesse +otr-require-encryption = + .label = Üks-ühele vestluste korral nõutakse otspunktkrüptimist +otr-require-encryption-info = + Nõudes otspunktkrüptimist, ei saadeta üks-ühele vestlustes sõnumeid juhul, + kui neid pole võimalik krüptida. Saabunud krüptimata sõnumeid ei kuvata + osana tavalisest vestlusest ja samuti neid ei logita. +otr-verify-nudge = + .label = Alati tuletatakse meelde, et verifitseerimata kontakt tuleb verifitseerida +otr-not-yet-available = pole veel saadaval diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/auth.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/auth.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/auth.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/auth.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,39 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +otr-auth = + .title = Verifitseeri kontakti identiteet + .buttonlabelaccept = Verifitseeri +# Variables: +# $name (String) - the screen name of a chat contact person +auth-title = Verifitseeri kasutaja { $name } identiteet +# Variables: +# $own_name (String) - the user's own screen name +auth-your-fp-value = { $own_name }, sinu sõrmejälg: +# Variables: +# $their_name (String) - the screen name of a chat contact +auth-their-fp-value = Kontakti { $their_name } sõrmejälg: +auth-help = Kontakti identiteedi verifitseerimine aitab tagada, et vestlus on tõeliselt privaatne, mistõttu on kolmandal osapoolel väga raske vestlust pealt kuulata või sellega manipuleerida. +auth-help-title = Verifitseerimise abi +auth-question-received = Kontakti poolt esitatud küsimus: +auth-yes = + .label = Jah +auth-no = + .label = Ei +auth-verified = Olen veendunud, et see on tõesti õige sõrmejälg. +auth-manual-verification = Käsitsi sõrmejälje kontrollimine +auth-question-and-answer = Küsimus ja vastus +auth-shared-secret = Jagatud saladus +auth-manual-verification-label = + .label = { auth-manual-verification } +auth-question-and-answer-label = + .label = { auth-question-and-answer } +auth-shared-secret-label = + .label = { auth-shared-secret } +auth-manual-instruction = Võta soovitud kontaktiga ühendust mõne muu autenditud kanali kaudu, näiteks OpenPGPga allkirjastatud e-kirja teel või telefoni teel. Te peaksite üksteisele ütlema oma sõrmejälje. (Sõrmejälg on krüptimisvõtit tuvastav kontrollsumma.) Kui sõrmejälg ühtib, siis peaksid sellest allolevas dialoogis kinnitamisega märku andma. +auth-how = Kuidas soovid oma kontakti isikut verifitseerida? +auth-qa-instruction = Mõtle küsimusele, millele vastust teate ainult sina ja sinu kontakt. Sisesta küsimus ja vastus ning seejärel oota, et sinu kontakt vastaks. Kui vastused ei ühti, siis võib teie kasutatav suhtluskanal olla varjatud jälgimise all. +auth-secret-instruction = Mõtle saladusele, mida ainult sina ja sinu kontakt teate. Ärge kasutage saladuse vahetamiseks sama interneti ühendust. Sisesta saladus ning seejärel oota, et sama teeks ka sinu kontakt. Kui saladused ei ühti, siis võib teie kasutatav suhtluskanal olla varjatud jälgimise all. +auth-question = Sisesta küsimus: +auth-answer = Sisesta vastus (tõstutundlik): +auth-secret = Sisesta saladus: diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/chat.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/chat.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/chat.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/chat.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -3,11 +3,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. state-label = Krüpteeringu olek: - start-text = Alusta krüpteeritud vestlusega - +start-label = + .label = { start-text } +start-tooltip = + .tooltiptext = { start-text } end-label = .label = Lõpeta krüpteeritud vestlus - auth-label = .label = Kontrolli kontakti identiteeti diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/finger.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/finger.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,18 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +otr-finger = + .buttonlabelaccept = Sulge + .title = Varem nähtud OTR-sõrmejäljed +otr-finger-title = Varem nähtud OTRi sõrmejäljed +finger-intro = OTRi võtmete sõrmejäljed varasematest otspunktkrüptitud vestustest. +finger-screen-name = + .label = Kontakt +finger-verified = + .label = Verifitseerimise olek +finger-fingerprint = + .label = Sõrmejälg +finger-remove = + .label = Eemalda valitud +finger-remove-all = + .label = Eemalda kõik diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/finger-sync.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/finger-sync.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/finger-sync.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/finger-sync.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +finger-yes = Verifitseeritud +finger-no = Verifitseerimata +finger-subset-title = Eemalda sõrmejäljed +finger-subset-message = Vähemalt üht sõrmejälge polnud võimalik eemaldada, sest vastavat võtit kasutatakse praegu aktiivses vestluses. +finger-remove-all-title = Eemalda kõik sõrmejäljed +finger-remove-all-message = Kas oled kindel, et soovid eemaldada kõik varem nähtud sõrmejäljed? Kõik varasemad OTRi identiteedi verifitseerimised lähevad kaotsi. diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/otr.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/otr.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/otr.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/otr.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,73 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-encryption-required-part1 = Sa üritasid saata krüptimata sõnumit kontaktile { $name }. Reeglina ei ole krüptimata sõnumid lubatud. +msgevent-encryption-required-part2 = Üritatakse alustata privaatset vestlust. Sõnum saadetakse uuesti, kui privaatne vestlus algab. +msgevent-encryption-error = Sõnumi krüptimisel esines viga. Sõnumit ei saadetud. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-connection-ended = Kontakt { $name } on juba krüptitud ühenduse sinuga sulgenud. Sõnumit ei saadetud, et vältida selle kogemata krüptimata saatmist. Palun lõpeta oma krüptitud vestlus või taaskäivita see. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-setup-error = Privaatse vestluse seadistamisel kontaktiga { $name } esines viga. +# Do not translate 'OTR' (name of an encryption protocol) +msgevent-msg-reflected = Sa saad iseenda OTR-sõnumeid. Sa kas üritad vestelda iseendaga või peegeldab keegi sulle sinu sõnumeid tagasi. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-msg-resent = Viimane sõnum kontaktile { $name } saadeti uuesti. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-not-private = Krüptitud sõnum kontaktilt { $name } oli loetamatu, sest sa ei suhtle praegu privaatselt. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-unreadable = Sa said kontaktilt { $name } loetamatu krüptitud sõnumi. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-malformed = Sa said kontaktilt { $name } vigase sõnumi. +# A Heartbeat is a technical message used to keep a connection alive. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-log-heartbeat-rcvd = Võeti vastu tukse kontaktilt { $name }. +# A Heartbeat is a technical message used to keep a connection alive. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-log-heartbeat-sent = Saadeti tukse kontaktile { $name }. +# Do not translate 'OTR' (name of an encryption protocol) +msgevent-rcvdmsg-general-err = Vestluse kaitsmisel OTRiga esines ootamatu viga. +# Variables: +# $name (String) - the screen name of a chat contact person +# $msg (string) - the message that was received. +msgevent-rcvdmsg-unencrypted = Järgnev sõnum kontaktilt { $name } polnud krüptitud: { $msg } +# Do not translate 'OTR' (name of an encryption protocol) +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-unrecognized = Sa said kontaktilt { $name } tundmatu OTR-sõnumi. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-for-other-instance = { $name } saatis sõnumi, mis oli mõeldud mingi muu seansi jaoks. Kui sa oled sisse logitud mitu korda, siis võis selle sõnumi saada mingi teine seanss. +# Variables: +# $name (String) - the screen name of a chat contact person +context-gone-secure-private = Algas privaatne vestlus kontaktiga { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +context-gone-secure-unverified = Algas krüptitud, aga verifitseerimata vestlus kontaktiga { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +context-still-secure = Edukalt värskendati krüptitud vestlust kontaktiga { $name }. +error-enc = Sõnumi krüptimisel esines viga. +# Variables: +# $name (String) - the screen name of a chat contact person +error-not-priv = Sa saatsid krüptitud andmed kontaktile { $name }, kes ei oodanud neid. +error-unreadable = Saatsid krüptitud loetamatu sõnumi. +error-malformed = Saatsid vigase andmesõnumi. +resent = [saadeti uuesti] +# Variables: +# $name (String) - the screen name of a chat contact person +tlv-disconnected = { $name } lõpetas oma krüptitud vestluse sinuga; sa peaksid tegema sama. +# Do not translate "Off-the-Record" and "OTR" which is the name of an encryption protocol +# Make sure that this string does NOT contain any numbers, e.g. like "3". +# Variables: +# $name (String) - the screen name of a chat contact person +query-msg = { $name } taotles salvestusvälist (OTR) krüptitud vestust. Kuid sul puudub selle toetamiseks plugin. Lisateabe saamiseks vaata https://en.wikipedia.org/wiki/Off-the-Record_Messaging diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/otr/otrUI.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/otr/otrUI.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,65 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +start-label = Alusta krüpteeritud vestlust +refresh-label = Värskenda krüptitud vestlust +auth-label = Verifitseeri kontakti identiteet +reauth-label = Verifitseeri kontakti identiteet uuesti +auth-cancel = Loobu +auth-cancel-access-key = L +auth-error = Kontakti identiteedi verifitseerimisel esines viga. +auth-success = Kontakti verifitseerimine lõpetati edukalt. +auth-success-them = Sinu kontakt verifitseeris edukalt sinu identiteedi. Sa võid soovida verifitseerida ka tema identiteedi, esitades enda küsimuse. +auth-fail = Kontakti identiteedi verifitseerimine ebaõnnestus. +auth-waiting = Oodatakse kontakti verifitseerimise lõpetamist… +finger-verify = Verifitseeri +finger-verify-access-key = V +finger-ignore = Ignoreeri +finger-ignore-access-key = I +# Do not translate 'OTR' (name of an encryption protocol) +buddycontextmenu-label = Lisa OTRi sõrmejälg +# Variables: +# $name (String) - the screen name of a chat contact person +alert-start = Üritatakse alustada krüptitud vestlust kontaktiga { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +alert-refresh = Üritatakse värskendada krüptitud vestlust kontaktiga { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +alert-gone-insecure = Krüptitud vestlus kontaktiga { $name } lõppes. +# Variables: +# $name (String) - the screen name of a chat contact person +finger-unseen = Kontakti { $name } identiteet pole veel verifitseeritud. Juhuslik pealtkuulamine pole võimalik, aga mõningase pingutusega võib keegi pealt kuulata. Jälgimise vältimiseks verifitseeri selle kontakti identiteet. +# Variables: +# $name (String) - the screen name of a chat contact person +finger-seen = { $name } võtab sinuga ühendust tundmatust arvutist. Juhuslik pealtkuulamine pole võimalik, aga mõningase pingutusega võib keegi pealt kuulata. Jälgimise vältimiseks verifitseeri selle kontakti identiteet. +state-not-private = Praegune vestlus pole privaatne. +state-generic-not-private = Praegune vestlus pole privaatne. +# Variables: +# $name (String) - the screen name of a chat contact person +state-unverified = Praegune vestlus on krüptitud, aga pole privaatne, sest kontakti { $name } identiteet pole veel verifitseeritud. +state-generic-unverified = Praegune vestlus on krüptitud, aga pole privaatne, sest mõned identiteedid pole veel verifitseeritud. +# Variables: +# $name (String) - the screen name of a chat contact person +state-private = Kontakti { $name } identiteet on verifitseeritud. Praegune vestlus on krüptitud ja privaatne. +state-generic-private = Praegune vestlus on krüptitud ja privaatne. +# Variables: +# $name (String) - the screen name of a chat contact person +state-finished = { $name } lõpetas oma krüptitud vestluse sinuga; sa peaksid tegema sama. +state-not-private-label = Ebaturvaline +state-unverified-label = Verifitseerimata +state-private-label = Privaatne +state-finished-label = Lõpetatud +# Variables: +# $name (String) - the screen name of a chat contact person +verify-request = { $name } taotles sinu identiteedi verifitseerimist. +# Variables: +# $name (String) - the screen name of a chat contact person +afterauth-private = Kontakti { $name } identiteet on verifitseeritud. +# Variables: +# $name (String) - the screen name of a chat contact person +afterauth-unverified = Kontakti { $name } identiteet pole verifitseeritud. +# Do not translate 'OTR' (name of an encryption protocol) +# Variables: +# $error (String) - contains an error message that describes the cause of the failure +otr-genkey-failed = OTRi salajase võtme genereerimine ebaõnnestus: { $error } diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/policies/policies-descriptions.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/policies/policies-descriptions.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/policies/policies-descriptions.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/policies/policies-descriptions.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -11,105 +11,83 @@ ## in the documentation section in about:policies. policy-3rdparty = Set policies that WebExtensions can access via chrome.storage.managed. - +policy-AppAutoUpdate = Enable or disable automatic application update. policy-AppUpdateURL = Set custom app update URL. - policy-Authentication = Configure integrated authentication for websites that support it. - +policy-BackgroundAppUpdate2 = Enable or disable the background updater. policy-BlockAboutAddons = Block access to the Add-ons Manager (about:addons). - policy-BlockAboutConfig = Block access to the about:config page. - policy-BlockAboutProfiles = Block access to the about:profiles page. - policy-BlockAboutSupport = Block access to the about:support page. - policy-CaptivePortal = Enable or disable captive portal support. - policy-CertificatesDescription = Add certificates or use built-in certificates. - policy-Cookies = Allow or deny websites to set cookies. - +policy-DisableBuiltinPDFViewer = Disable PDF.js, the built-in PDF viewer in { -brand-short-name }. +policy-DisabledCiphers = Disable ciphers. policy-DefaultDownloadDirectory = Set the default download directory. - policy-DisableAppUpdate = Prevent { -brand-short-name } from updating. - +policy-DisableDefaultClientAgent = Prevent the default client agent from taking any actions. Only applicable to Windows; other platforms don’t have the agent. policy-DisableDeveloperTools = Block access to the developer tools. - policy-DisableFeedbackCommands = Disable commands to send feedback from the Help menu (Submit Feedback and Report Deceptive Site). - policy-DisableForgetButton = Prevent access to the Forget button. - +policy-DisableFormHistory = Don’t remember search and form history. policy-DisableMasterPasswordCreation = If true, a master password can’t be created. - +policy-DisablePasswordReveal = Do not allow passwords to be revealed in saved logins. policy-DisableProfileImport = Disable the menu command to Import data from another application. - policy-DisableSafeMode = Disable the feature to restart in Safe Mode. Note: the Shift key to enter Safe Mode can only be disabled on Windows using Group Policy. - policy-DisableSecurityBypass = Prevent the user from bypassing certain security warnings. - policy-DisableSystemAddonUpdate = Prevent { -brand-short-name } from installing and updating system add-ons. - policy-DisableTelemetry = Turn off Telemetry. - policy-DisplayMenuBar = Display the Menu Bar by default. - policy-DNSOverHTTPS = Configure DNS over HTTPS. - policy-DontCheckDefaultClient = Disable check for default client on startup. - policy-DownloadDirectory = Set and lock the download directory. - # “lock” means that the user won’t be able to change this setting policy-EnableTrackingProtection = Enable or disable Content Blocking and optionally lock it. - +# “lock” means that the user won’t be able to change this setting +policy-EncryptedMediaExtensions = Enable or disable Encrypted Media Extensions and optionally lock it. # A “locked” extension can’t be disabled or removed by the user. This policy # takes 3 keys (“Install”, ”Uninstall”, ”Locked”), you can either keep them in # English or translate them as verbs. policy-Extensions = Install, uninstall or lock extensions. The Install option takes URLs or paths as parameters. The Uninstall and Locked options take extension IDs. - policy-ExtensionSettings = Manage all aspects of extension installation. - policy-ExtensionUpdate = Enable or disable automatic extension updates. - +policy-Handlers = Configure default application handlers. policy-HardwareAcceleration = If false, turn off hardware acceleration. - policy-InstallAddonsPermission = Allow certain websites to install add-ons. +policy-LegacyProfiles = Disable the feature enforcing a separate profile for each installation. ## Do not translate "SameSite", it's the name of a cookie attribute. +policy-LegacySameSiteCookieBehaviorEnabled = Enable default legacy SameSite cookie behavior setting. +policy-LegacySameSiteCookieBehaviorEnabledForDomainList = Revert to legacy SameSite behavior for cookies on specified sites. + ## policy-LocalFileLinks = Allow specific websites to link to local files. - +policy-ManualAppUpdateOnly = Allow manual updates only and do not notify the user about updates. policy-NetworkPrediction = Enable or disable network prediction (DNS prefetching). - policy-OfferToSaveLogins = Enforce the setting to allow { -brand-short-name } to offer to remember saved logins and passwords. Both true and false values are accepted. - +policy-OfferToSaveLoginsDefault = Set the default value for allowing { -brand-short-name } to offer to remember saved logins and passwords. Both true and false values are accepted. policy-OverrideFirstRunPage = Override the first run page. Set this policy to blank if you want to disable the first run page. - policy-OverridePostUpdatePage = Override the post-update “What’s New” page. Set this policy to blank if you want to disable the post-update page. - +policy-PasswordManagerEnabled = Enable saving passwords to the password manager. +# PDF.js and PDF should not be translated +policy-PDFjs = Disable or configure PDF.js, the built-in PDF viewer in { -brand-short-name }. +policy-Permissions2 = Configure permissions for camera, microphone, location, notifications, and autoplay. policy-Preferences = Set and lock the value for a subset of preferences. - +policy-PrimaryPassword = Require or prevent using a Primary Password. policy-PromptForDownloadLocation = Ask where to save files when downloading. - policy-Proxy = Configure proxy settings. - policy-RequestedLocales = Set the list of requested locales for the application in order of preference. - policy-SanitizeOnShutdown2 = Clear navigation data on shutdown. - policy-SearchEngines = Configure search engine settings. This policy is only available on the Extended Support Release (ESR) version. - +policy-SearchSuggestEnabled = Enable or disable search suggestions. # For more information, see https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11/Module_Installation policy-SecurityDevices = Install PKCS #11 modules. - policy-SSLVersionMax = Set the maximum SSL version. - policy-SSLVersionMin = Set the minimum SSL version. - policy-SupportMenu = Add a custom support menu item to the help menu. - +policy-UserMessaging = Don’t show certain messages to the user. # “format” refers to the format used for the value of this policy. policy-WebsiteFilter = Block websites from being visited. See documentation for more details on the format. diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/am-copies.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/am-copies.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/am-copies.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/am-copies.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +account-prefs-show-address-row-description = Aadressiriba alati kuvamiseks uue kirja alustamisel jäta aadressiväli tühjaks. diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/am-im.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/am-im.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/am-im.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/am-im.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,20 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +account-settings-title = Autentimise sätted +account-channel-title = Vaikekanalid +chat-autologin = + .label = Käivitumisel logitakse sisse +chat-encryption-generic = Üldine +chat-encryption-log = + .label = otspunktkrüptitud sõnumid kaasatakse vestluste logidesse +chat-encryption-label = Otspunktkrüptimine +chat-encryption-description = { $protocol } pakub vestlustele otspunktkrüptimist. See takistab kolmandatel isikutel vestlust pealt kuulamast. Krüptimise toimimiseks võib allpool vaja minna täiendavat seadistamist. +chat-encryption-status = Krüptimise olek +chat-encryption-placeholder = Krüptimist pole alustatud. +chat-encryption-sessions = Seansid +chat-encryption-sessions-description = Otspunktkrüptimise korrektseks töötamiseks pead usaldama teisi sinu kontosse sisse logitud seansse. Seansi verifitseerimiseks on vajalik suhtlus teise kliendiga. Seansi verifitseerimine võib viia selleni, et kõik seansid on usaldatud ka { -brand-short-name }i poolt. +chat-encryption-session-verify = verifitseeri + .title = Verifitseeri selle seansi identiteet +chat-encryption-session-trusted = usaldatud + .title = Selle seansi identiteet on verifitseeritud diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/connection.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/connection.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/connection.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/connection.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -4,20 +4,16 @@ connection-dns-over-https-url-resolver = Teenusepakkuja .accesskey = T - # Variables: # $name (String) - Display name or URL for the DNS over HTTPS provider connection-dns-over-https-url-item-default = .label = { $name } (vaikimisi) .tooltiptext = Kasuta üle HTTPSi töötava DNSi puhul vaikeaadressi - connection-dns-over-https-url-custom = .label = kohandatud .accesskey = o .tooltiptext = Sisesta üle HTTPSi töötava DNSi jaoks oma eelistatud URL - connection-dns-over-https-custom-label = Kohandatud - connection-dialog-window = .title = Ühenduse sätted .style = @@ -25,76 +21,74 @@ [macos] width: 44em !important *[other] width: 49em !important } - -connection-proxy-legend = Puhverserverite häälestamine internetti pääsemiseks - +connection-disable-extension = + .label = Keela laiendus +disable-extension-button = Keela laiendus +# Variables: +# $name (String) - The extension that is controlling the proxy settings. +# +# The extension-icon is the extension's icon, or a fallback image. It should be +# purely decoration for the actual extension name, with alt="". +proxy-settings-controlled-by-extension = Laiendus { $name } kontrollib seda, kuidas { -brand-short-name } ühendub internetti. +connection-proxy-legend = Interneti puhverserveri häälestamine proxy-type-no = .label = Puhverserver puudub .accesskey = P - proxy-type-wpad = .label = Puhverserveri sätted tuvastatakse automaatselt .accesskey = h - proxy-type-system = .label = Kasutatakse süsteemseid puhverserveri sätteid .accesskey = u - proxy-type-manual = .label = Puhverserveri häälestamine käsitsi: .accesskey = K - proxy-http-label = .value = HTTP: .accesskey = H - http-port-label = .value = Port: .accesskey = P - +proxy-http-sharing = + .label = Seda puhverserverit kasutatakse ka HTTPSi jaoks + .accesskey = S +proxy-https-label = + .value = HTTPS-puhverserver: + .accesskey = h ssl-port-label = .value = Port: .accesskey = o - proxy-socks-label = .value = SOCKS masin: .accesskey = C - socks-port-label = .value = Port: .accesskey = t - proxy-socks4-label = .label = SOCKS v4 .accesskey = K - proxy-socks5-label = .label = SOCKS v5 .accesskey = v - proxy-type-auto = .label = Puhverserveri automaatse häälestuse URL: .accesskey = a - proxy-reload-label = .label = Laadi uuesti .accesskey = L - no-proxy-label = .value = Erandid: .accesskey = d - no-proxy-example = Näide: .mozilla.org, .net.nz, 192.168.1.0/24 - +# Do not translate "localhost", "127.0.0.1/8" and "::1". (You can translate "and".) +connection-proxy-noproxy-localhost-desc-2 = Ühendusi järgnevatele aadressidele ei suunata kunagi puhverserverisse: localhost, 127.0.0.1/8 ja ::1. proxy-password-prompt = .label = Salvestatud paroolide korral autentimist ei küsita .accesskey = r .tooltiptext = Selle valiku korral autenditakse sind automaatselt puhverserveritega, mille parool on salvestatud. Parooli küsitakse juhul, kui autentimine ebaõnnestub. - proxy-remote-dns = .label = Puhverserveri DNS, kui kasutusel on SOCKS v5 .accesskey = D - proxy-enable-doh = .label = Lubatakse DNS üle HTTPSi .accesskey = D diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/dock-options.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/dock-options.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/dock-options.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/dock-options.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -5,22 +5,20 @@ dock-options-window-dialog = .title = Rakenduse ikooni sätted .style = width: 35em; - +dock-options-show-badge = + .label = Kuvatakse ikooni loendurit + .accesskey = v bounce-system-dock-icon = .label = Uue kirja saabumisel animeeritakse ikooni .accesskey = i - dock-icon-legend = Rakenduse ikooni valikud - dock-icon-show-label = .value = Rakenduse ikoonil kuvatakse: - count-unread-messages-radio = .label = lugemata kirjade arvu .accesskey = l - count-new-messages-radio = .label = uute kirjade arvu .accesskey = u - notification-settings-info = Rakenduse ikooni loendur on võimalik keelata süsteemi seadetes, teavituste paneelis. +notification-settings-info2 = Rakenduse ikooni loendur on võimalik keelata süsteemi sätetes, teavituste paneelis. diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/fonts.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/fonts.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/fonts.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/fonts.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -4,21 +4,17 @@ fonts-window-close = .key = w - # Variables: # $name {string, "Arial"} - Name of the default font fonts-label-default = .label = vaikimisi ({ $name }) fonts-label-default-unnamed = .label = vaikimisi - fonts-encoding-dialog-title = .title = Fondid ja kodeeringud - fonts-language-legend = .value = Fondid keelele: .accesskey = F - fonts-proportional-label = .value = Standardne: .accesskey = S @@ -89,41 +85,35 @@ default-font-serif = .label = Seriifidega - default-font-sans-serif = .label = Seriifideta - +font-size-proportional-label = + .value = Suurus: + .accesskey = u font-size-monospace-label = .value = Suurus: .accesskey = r - font-serif-label = .value = Seriifidega: .accesskey = f - font-sans-serif-label = .value = Seriifideta: .accesskey = e - font-monospace-label = .value = Fikseeritud laiusega: .accesskey = k - font-min-size-label = .value = Vähim kirja suurus: .accesskey = V - min-size-none = .label = Puudub ## Fonts in message font-control-legend = Fontide haldus - use-document-fonts-checkbox = .label = Kirjades lubatakse kasutada muid fonte .accesskey = l - use-fixed-width-plain-checkbox = .label = Lihttekstiga kirjade puhul kasutatakse kindla laiusega fonti .accesskey = h @@ -131,17 +121,13 @@ ## Language settings text-encoding-legend = Teksti kodeering - text-encoding-description = Määra vaikimisi kodeering kirjade saamiseks ja saatmiseks - font-outgoing-email-label = .value = Väljuvad kirjad: .accesskey = j - font-incoming-email-label = .value = Saabuvad kirjad: .accesskey = k - default-font-reply-checkbox = .label = Võimalusel kasutatakse vastustes vaikimisi teksti kodeeringut .accesskey = d diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/new-tag.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/new-tag.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/new-tag.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/new-tag.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -4,8 +4,9 @@ tag-dialog-window = .title = Uue sildi loomine - tag-name-label = .value = Sildi nimi: .accesskey = S - +tag-color-label = + .value = Värv: + .accesskey = V diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/offline.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/offline.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/offline.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/offline.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -4,51 +4,39 @@ offline-dialog-window = .title = Võrguta režiimi sätted - autodetect-online-label = .label = Järgitakse automaatselt tuvastatud võrgurežiimi .accesskey = J - +offline-preference-startup-label = Käivitamisel kasutatav käsitsi määratud olek: status-radio-remember = .label = kasutatakse eelnenud võrgurežiimi olekut .accesskey = u - status-radio-ask = .label = küsitakse võrgurežiimi oleku kohta .accesskey = k - status-radio-always-online = .label = alustatakse alati võrgurežiimis .accesskey = v - status-radio-always-offline = .label = alustatakse alati võrguta režiimis .accesskey = r - going-online-label = Kas saata võrgurežiimi lülitudes saatmata kirjad? - going-online-auto = .label = jah .accesskey = h - going-online-not = .label = ei .accesskey = e - going-online-ask = .label = küsitakse .accesskey = s - going-offline-label = Kas tõmmata võrguta režiimi lülitudes kirjad, et neid võrguta režiimis kasutada? - going-offline-auto = .label = jah .accesskey = a - going-offline-not = .label = ei .accesskey = i - going-offline-ask = .label = küsitakse .accesskey = t diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/passwordManager.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/passwordManager.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/passwordManager.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/passwordManager.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -6,6 +6,10 @@ .title = Salvestatud kasutajakontod window-close = .key = w +focus-search-primary-shortcut = + .key = f +focus-search-alt-shortcut = + .key = k copy-provider-url-cmd = .label = Kopeeri URL .accesskey = K @@ -44,7 +48,9 @@ import = .label = Impordi... .accesskey = I - +password-close-button = + .label = Sulge + .accesskey = S show-passwords = .label = Kuva paroole .accesskey = v @@ -65,3 +71,12 @@ ## OS Authentication dialog +# This message can be seen by trying to show or copy the passwords. +password-os-auth-dialog-message = Salvestatud paroolide kuvamiseks kinnitage oma identiteet. +# This message can be seen by trying to show or copy the passwords. +# The macOS strings are preceded by the operating system with "Thunderbird is trying to " +# and includes subtitle of "Enter password for the user "xxx" to allow this." These +# notes are only valid for English. Please test in your locale. +password-os-auth-dialog-message-macosx = kuva salvestatud paroole +# Don't change this label. +password-os-auth-dialog-caption = { -brand-full-name } diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/permissions.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/permissions.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/permissions.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/permissions.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -5,49 +5,39 @@ permissions-reminder-window = .title = Erandid .style = width: 36em; - +permission-preferences-close-window = + .key = w website-address-label = .value = Veebilehe aadress: .accesskey = d - block-button = .label = Bloki .accesskey = B - allow-session-button = .label = Luba selleks seansiks .accesskey = s - allow-button = .label = Luba .accesskey = a - treehead-sitename-label = .label = Veebileht - treehead-status-label = .label = Olek - remove-site-button = .label = Eemalda veebileht .accesskey = E - remove-all-site-button = .label = Eemalda kõik veebilehed .accesskey = k - cancel-button = .label = Loobu .accesskey = o - save-button = .label = Salvesta muudatused .accesskey = S - permission-can-label = Lubatud permission-can-access-first-party-label = Luba esimese osapoole küpsised permission-can-session-label = Lubatud seansi jooksul permission-cannot-label = Blokitud - invalid-uri-message = Palun sisesta korrektne masinanimi invalid-uri-title = Sisestatud masinanimi on vigane diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/preferences.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,87 +2,74 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - close-button = .aria-label = Sulge - +preferences-doc-title = Sätted +preferences-doc-title2 = Sätted +category-list = + .aria-label = Kategooriad pane-general-title = Üldine category-general = .tooltiptext = { pane-general-title } - pane-compose-title = Koostamine category-compose = .tooltiptext = Koostamine - pane-privacy-title = Privaatsus ja turvalisus category-privacy = .tooltiptext = Privaatsus ja turvalisus - pane-chat-title = Kiirsuhtlus category-chat = .tooltiptext = Kiirsuhtlus - pane-calendar-title = Kalender category-calendar = .tooltiptext = Kalender - general-language-and-appearance-header = Keel ja välimus - general-incoming-mail-header = Saabuvad kirjad: - general-files-and-attachment-header = Failid ja manused - general-tags-header = Sildid - general-reading-and-display-header = Lugemine ja kuvamine - general-updates-header = Uuendused - general-network-and-diskspace-header = Võrk ja kettaruum - general-indexing-label = Indekseerimine - composition-category-header = Koostamine - composition-attachments-header = Manused - composition-spelling-title = Õigekiri - compose-html-style-title = HTML-stiil - composition-addressing-header = Adresseerimine - privacy-main-header = Privaatsus - privacy-passwords-header = Paroolid - privacy-junk-header = Rämpspost - +collection-header = { -brand-short-name }i andmete kogumine ja kasutamine +collection-description = Me pingutame, et pakkuda sulle erinevaid valikuvõimalusi, ja kogume ainult neid andmeid, mis aitavad meil { -brand-short-name }i paremaks muuta kõigi jaoks. Isiklike andmete puhul küsime me alati enne saatmist luba. +collection-privacy-notice = Privaatsusreeglid +collection-health-report-telemetry-disabled = Sa ei luba enam { -vendor-short-name }il koguda tehnilisi andmeid. Kõik varasemad andmed kustutatakse 30 päeva jooksul. +collection-health-report-telemetry-disabled-link = Rohkem teavet +collection-health-report = + .label = { -brand-short-name }il lubatakse automaatselt saata tehnilisi andmeid { -vendor-short-name }le + .accesskey = l +collection-health-report-link = Rohkem teavet +# This message is displayed above disabled data sharing options in developer builds +# or builds with no Telemetry support available. +collection-health-report-disabled = Selle kompileerimise konfiguratsiooniga on andmete raporteerimine keelatud +collection-backlogged-crash-reports = + .label = { -brand-short-name }il lubatakse saatmata vearaporteid saata + .accesskey = s +collection-backlogged-crash-reports-link = Rohkem teavet privacy-security-header = Turvalisus - privacy-scam-detection-title = Kelmuse tuvastamine - privacy-anti-virus-title = Viirusetõrje - privacy-certificates-title = Serdid - chat-pane-header = Kiirsuhtlus - chat-status-title = Olek - chat-notifications-title = Teavitused - chat-pane-styling-header = Kujundus - choose-messenger-language-description = Vali keeled, mida kasutatakse menüüde, sõnumite ja { -brand-short-name }ilt tulevate teavituste kuvamiseks. manage-messenger-languages-button = .label = Määra alternatiivsed keeled… .accesskey = M confirm-messenger-language-change-description = Muudatuste rakendamiseks taaskäivita { -brand-short-name } confirm-messenger-language-change-button = Rakenda ja taaskäivita - update-setting-write-failure-title = Uuendamise sätete salvestamisel esines viga - # Variables: # $path (String) - Path to the configuration file # The newlines between the main text and the line containing the path is @@ -91,18 +78,26 @@ { -brand-short-name }il esines viga ja muudatust ei salvestatud. Antud sätte muutmiseks on vajalikud õigused alloleva faili muutmiseks. Probleem võib laheneda, kui sina või sinu süsteemiadministraator annab Users grupile täielikud muutmise õigused sellele failile. Järgmist faili polnud võimalik muuta: { $path } - update-in-progress-title = Uuendamine - update-in-progress-message = Kas soovid, et { -brand-short-name } jätkaks uuendamisega? - update-in-progress-ok-button = &Loobu # Continue is the cancel button so pressing escape or using a platform standard # method of closing the UI will not discard the update. update-in-progress-cancel-button = &Jätka +account-button = Kontode sätted +open-addons-sidebar-button = Lisad ja teemad ## OS Authentication dialog +# This message can be seen by trying to add a Primary Password. +primary-password-os-auth-dialog-message-win = Ülemparooli loomiseks sisesta Windowsi sisselogimisandmed. See aitab kaitsta sinu kontode turvalisust. +# This message can be seen by trying to add a Primary Password. +# The macOS strings are preceded by the operating system with "Thunderbird is trying to " +# and includes subtitle of "Enter password for the user "xxx" to allow this." These +# notes are only valid for English. Please test in your locale. +primary-password-os-auth-dialog-message-macosx = create a Primary Password +# Don't change this label. +master-password-os-auth-dialog-caption = { -brand-full-name } ## General Tab @@ -110,28 +105,30 @@ .key = F focus-search-shortcut-alt = .key = K - general-legend = { -brand-short-name }i avaleht - start-page-label = .label = { -brand-short-name }i käivitumisel näidatakse kirja alas avalehte .accesskey = i - location-label = .value = Asukoht: .accesskey = o restore-default-label = .label = Taasta algväärtus .accesskey = T - default-search-engine = Vaikeotsingumootor -add-search-engine = - .label = Lisa failist - .accesskey = f +add-web-search-engine = + .label = Lisa… + .accesskey = L remove-search-engine = .label = Eemalda .accesskey = E - +add-opensearch-provider-title = Lisa OpenSearchi teenusepakkuja +add-opensearch-provider-text = Sisesta lisatava OpenSearchi teenusepakkuja URL. Kasuta kas otsest kirjeldusfaili URLi või automaatselt tuvastamise URLi. +adding-opensearch-provider-failed-title = OpenSearchi teenusepakkuja lisamine ebaõnnestus. +adding-opensearch-provider-failed-text = OpenSearchi teenusepakkujat URLile { $url } polnud võimalik lisada. +minimize-to-tray-label = + .label = { -brand-short-name }i minimeerimisel liigutatakse see salve + .accesskey = m new-message-arrival = Uue kirja saabumisel: mail-play-sound-label = .label = @@ -147,48 +144,48 @@ mail-play-button = .label = Esita .accesskey = E - change-dock-icon = Rakenduse ikooni sätete muutmine app-icon-options = .label = Rakenduse ikooni sätted… .accesskey = n - notification-settings = Teated ja vaikimisi heli saab välja lülitada paneelilt Teavitused süsteemi eelistustes. - +notification-settings2 = Teated ja vaikimisi heli saab välja lülitada paneelilt Teavitused süsteemi sätetest. animated-alert-label = .label = kuvatakse teadet .accesskey = u customize-alert-label = .label = Kohanda... .accesskey = K - +biff-use-system-alert = + .label = Kasutatakse süsteemi teavitust +tray-icon-unread-label = + .label = Salves kuvatakse lugemata kirjade ikooni + .accesskey = v +tray-icon-unread-description = Soovitatav tegumiriba väikeste nuppude kasutamisel +mail-system-sound-label = + .label = süsteemi vaikimisi uue kirja heli + .accesskey = t mail-custom-sound-label = .label = kasutatakse järgnevat helifaili .accesskey = e mail-browse-sound-button = .label = Lehitse... .accesskey = L - enable-gloda-search-label = .label = Lubatakse kirjade üldotsing ja indekseerimine .accesskey = L - datetime-formatting-legend = Kuupäeva ja kellaaja vorming language-selector-legend = Keel - allow-hw-accel = .label = Võimalusel kasutatakse riistvaralist kiirendust .accesskey = V - store-type-label = .value = Uute kontode kirjade salvestamise viis: .accesskey = U - mbox-store-label = .label = üks fail kausta kohta (mbox) maildir-store-label = .label = iga kiri eraldi failis (maildir) - scrolling-legend = Kerimine autoscroll-label = .label = Kasutatakse automaatset kerimist @@ -196,7 +193,9 @@ smooth-scrolling-label = .label = Kasutatakse sujuvat kerimist .accesskey = s - +browsing-gtk-use-non-overlay-scrollbars = + .label = Kerimisribasid kuvatakse alati + .accesskey = K system-integration-legend = Süsteemi integratsioon always-check-default = .label = Käivitumisel kontrollitakse alati, kas { -brand-short-name } on e-posti vaikeklient @@ -204,7 +203,6 @@ check-default-button = .label = Kontrolli nüüd… .accesskey = n - # Note: This is the search engine name for all the different platforms. # Platforms that don't support it should be left blank. search-engine-name = @@ -213,26 +211,20 @@ [windows] Windows Search *[other] { "" } } - search-integration-label = .label = Rakendusel { search-engine-name } on kirjade otsimine lubatud .accesskey = R - config-editor-button = .label = Konfiguratsiooni redaktor... .accesskey = n - return-receipts-description = Määra, kuidas { -brand-short-name } käsitleb kättesaamise kinnitusi return-receipts-button = .label = Kättesaamise kinnitused... .accesskey = M - update-app-legend = { -brand-short-name }i uuendused - # Variables: # $version (String): version of Thunderbird, e.g. 68.0.1 update-app-version = Versioon { $version } - allow-description = { -brand-short-name }il lubatakse automatic-updates-label = .label = uuendused automaatselt paigaldada (soovitatav: parem turvalisus) @@ -240,36 +232,30 @@ check-updates-label = .label = kontrollida uuenduste olemasolu, paigaldamise kohta küsitakse kinnitust .accesskey = k - update-history-button = .label = Näita uuenduste ajalugu .accesskey = j - use-service = .label = Uuenduste paigaldamiseks kasutatakse taustateenust .accesskey = U - cross-user-udpate-warning = See säte rakendub kõigile Windowsi kontodele ja { -brand-short-name }i profiilidele, mis kasutavad seda { -brand-short-name }i paigaldust. - networking-legend = Ühendus proxy-config-description = Määra, kuidas { -brand-short-name } ühendub internetti. - network-settings-button = .label = Sätted... .accesskey = d - offline-legend = Ühenduseta offline-settings = Võrguta režiimi häälestamine - offline-settings-button = .label = Sätted .accesskey = S - diskspace-legend = Kettaruum offline-compact-folder = .label = Kõik kaustad surutakse kokku, kui see säästab kokku rohkem kui .accesskey = b - +offline-compact-folder-automatically = + .label = Küsitakse iga kord enne tihendamist + .accesskey = g compact-folder-size = .value = MiB @@ -280,7 +266,6 @@ use-cache-before = .value = Vahemäluks kasutatakse kuni .accesskey = V - use-cache-after = MiB mälu ## @@ -288,42 +273,31 @@ smart-cache-label = .label = Keelatakse automaatne vahemälu haldamine .accesskey = u - clear-cache-button = .label = Puhasta nüüd .accesskey = P - fonts-legend = Fondid ja värvid - default-font-label = .value = Vaikimisi font: .accesskey = V - default-size-label = .value = Suurus: .accesskey = S - font-options-button = .label = Fondid... .accesskey = F - color-options-button = .label = Värvid… .accesskey = r - display-width-legend = Lihttekstis kirjad - # Note : convert-emoticons-label 'Emoticons' are also known as 'Smileys', e.g. :-) convert-emoticons-label = .label = Emotikonide graafiline esitamine .accesskey = m - display-text-label = Tsiteeritud lihttekstiga kirjade kuvamine: - style-label = .value = Stiil: .accesskey = t - regular-style-item = .label = tavaline bold-style-item = @@ -332,34 +306,25 @@ .label = kaldkiri bold-italic-style-item = .label = paks kaldkiri - size-label = .value = Suurus: .accesskey = S - regular-size-item = .label = tavaline bigger-size-item = .label = suurem smaller-size-item = .label = väiksem - quoted-text-color = .label = Värv: .accesskey = V - -type-column-label = - .label = Sisu tüüp - .accesskey = S - -action-column-label = - .label = Tegevus - .accesskey = T - +search-handler-table = + .placeholder = Filtreeri sisu tüüpe ja tegevusi +type-column-header = Sisu tüüp +action-column-header = Tegevus save-to-label = .label = Failid salvestatakse asukohta .accesskey = F - choose-folder-label = .label = { PLATFORM() -> @@ -371,30 +336,22 @@ [macos] L *[other] L } - always-ask-label = .label = Alati küsitakse, kuhu failid salvestatakse .accesskey = A - - display-tags-text = Silte saab kasutada kirjade kategoriseerimiseks ja prioriteedi määramiseks. - new-tag-button = .label = Uus… .accesskey = U - edit-tag-button = .label = Redigeeri… .accesskey = R - delete-tag-button = .label = Kustuta .accesskey = K - auto-mark-as-read = .label = Kirjad märgitakse automaatselt loetuks .accesskey = K - mark-read-no-delay = .label = kohe pärast kuvamist .accesskey = o @@ -405,33 +362,26 @@ mark-read-delay = .label = märgitakse loetuks pärast .accesskey = m - seconds-label = sekundit ## open-msg-label = .value = Kirjad avatakse: - open-msg-tab = .label = uuel kaardil .accesskey = u - open-msg-window = .label = uues aknas .accesskey = a - open-msg-ex-window = .label = samas aknas .accesskey = s - close-move-delete = .label = Kustutamisel või liigutamisel kirja aken/kaart suletakse .accesskey = K - display-name-label = .value = Kuvatav nimi: - condensed-addresses-label = .label = Aadressiraamatus olevate kontaktide puhul näidatakse ainult kuvatavat nime .accesskey = k @@ -441,13 +391,10 @@ forward-label = .value = Kirjad edastatakse: .accesskey = K - inline-label = .label = tekstina - as-attachment-label = .label = manusena - extension-label = .label = failinimele lisatakse laiend .accesskey = f @@ -458,7 +405,6 @@ auto-save-label = .label = Salvestatakse automaatselt iga .accesskey = o - auto-save-end = minuti järel ## @@ -466,236 +412,182 @@ warn-on-send-accel-key = .label = Küsitakse kinnitust, kui kiri saadetakse klahvide kiirkombinatsiooni abil .accesskey = t - spellcheck-label = .label = Enne saatmist kontrollitakse õigekirja .accesskey = E - spellcheck-inline-label = .label = Sisestamisel kontrollitakse õigekirja .accesskey = k - language-popup-label = .value = Keel: .accesskey = K - download-dictionaries-link = Hangi veel sõnaraamatuid - font-label = .value = Font: .accesskey = n - font-size-label = .value = Suurus: .accesskey = u - default-colors-label = .label = Kasutatakse kuvamise vaikevärve .accesskey = v - font-color-label = .value = Teksti värv: .accesskey = k - bg-color-label = .value = Taustavärv: .accesskey = v - restore-html-label = .label = Lähtesta .accesskey = a - default-format-label = .label = Vaikimisi kasututatakse lõiguvormingut .accesskey = e - format-description = Muuda saadetavate kirjade teksti vormingut - send-options-label = .label = Saatmise valikud... .accesskey = S - autocomplete-description = Kirjade adresseerimisel otsitakse sobivaid vasteid: - ab-label = .label = kohalikest aadressiraamatutest .accesskey = a - directories-label = .label = kataloogiserverist: .accesskey = k - directories-none-label = .none = puudub - edit-directories-label = .label = Redigeeri katalooge... .accesskey = R - email-picker-label = .label = Väljuvate kirjade adressaadid lisatakse automaatselt: .accesskey = k - default-directory-label = .value = Käivitumisel aadressiraamatu aknas kuvatav vaikekataloog: .accesskey = i - default-last-label = .none = Viimasena kasutatud kataloog - attachment-label = .label = Kontrollitakse puuduvat manust .accesskey = K - attachment-options-label = .label = Võtmesõnad… .accesskey = V - enable-cloud-share = .label = Pilveteenuste kasutamist pakutakse suuremate failide puhul kui cloud-share-size = .value = MiB - add-cloud-account = .label = Lisa… .accesskey = L .defaultlabel = Lisa… - remove-cloud-account = .label = Eemalda .accesskey = E - find-cloud-providers = .value = Leia veel teenusepakkujaid… - cloud-account-description = Lisa uus pilveteenus - ## Privacy Tab mail-content = E-posti sisu - remote-content-label = .label = Kirjades lubatakse väline sisu .accesskey = i - exceptions-button = .label = Erandid… .accesskey = E - remote-content-info = .value = Rohkem teavet välise sisuga seonduvatest privaatsuse probleemidest - web-content = Veebisisu - history-label = .label = Külastatud saidid ja lingid peetakse meeles .accesskey = a - cookies-label = .label = Küpsised lubatakse .accesskey = K - third-party-label = .value = Kolmanda osapoole küpsised lubatakse: .accesskey = o - third-party-always = .label = alati third-party-never = .label = mitte kunagi third-party-visited = .label = varem külastatud saitidelt - keep-label = .value = Säilitatakse kuni: .accesskey = l - keep-expire = .label = nad aeguvad keep-close = .label = { -brand-short-name } suletakse keep-ask = .label = küsitakse iga kord - cookies-button = .label = Näita küpsiseid… .accesskey = S - do-not-track-label = .label = Saitidele saadetakse signaal, et sa ei soovi olla jälitatud .accesskey = s - learn-button = .label = Rohkem teavet - passwords-description = { -brand-short-name } võib paroolide infot meeles pidada, et sa ei peaks logimisel neid uuesti sisestama. - passwords-button = .label = Salvestatud paroolid… .accesskey = S - - +primary-password-description = Kui ülemparool on määratud, kaitseb see sinu paroole, kuid sa pead sisestama selle seansi alguses. +primary-password-label = + .label = Kasutatakse ülemparooli + .accesskey = s +primary-password-button = + .label = Muuda ülemparooli… + .accesskey = M +forms-primary-pw-fips-title = Sa oled FIPS-režiimis. See eeldab, et sinu ülemparool ei oleks tühi. +forms-master-pw-fips-desc = Parooli muutmine ebaõnnestus junk-description = Määra oma vaikimisi rämpsposti sätted. Kontopõhiseid rämpsposti sätteid saab häälestada konto sätetes. - junk-label = .label = Kui kirjad märgitakse rämpspostiks: .accesskey = K - junk-move-label = .label = liigutatakse nad konto "Rämpspost" kausta .accesskey = l - junk-delete-label = .label = need kustutatakse .accesskey = t - junk-read-label = .label = Rämpspostiks määratud kirjad märgitakse loetuks .accesskey = k - junk-log-label = .label = Kohastuva rämpsposti filtri logimine lubatakse .accesskey = f - junk-log-button = .label = Kuva logi .accesskey = u - reset-junk-button = .label = Lähtesta rämpsposti filtrid .accesskey = r - phishing-description = { -brand-short-name } saab kirju analüüsida, et avastada tuntumaid e-posti pettuste skeeme, millega üritatakse kasutajaid tüssata. - phishing-label = .label = Teavitatakse, kui kirja peetakse petukirjaks .accesskey = T - antivirus-description = { -brand-short-name } võib saabuvate kirjade analüüsimise enne nende lokaalset salvestamist viirustõrje tarkvarale lihtsamaks teha. - antivirus-label = .label = Viirustõrje tarkvaral lubatakse üksikuid saabuvaid kirju karantiini panna .accesskey = i - certificate-description = Kui server nõuab kasutaja isiklikku sertifikaati: - certificate-auto = .label = valitakse üks automaatselt .accesskey = v - certificate-ask = .label = küsitakse iga kord .accesskey = k - ocsp-label = .label = Sertifikaatide valideeruvust kontrollitakse OCSP abil .accesskey = S - certificate-button = .label = Halda sertifikaate… .accesskey = H - security-devices-button = .label = Turvaseadmed… .accesskey = T @@ -705,10 +597,8 @@ startup-label = .value = { -brand-short-name }i käivitumisel: .accesskey = k - offline-label = .label = jäetakse kiirsuhtluse kontod ühendamata - auto-connect-label = .label = ühendatakse kiirsuhtluse kontod automaatselt @@ -721,7 +611,6 @@ idle-label = .label = Kontaktidele antakse jõudeolekust teada .accesskey = o - idle-time-label = minuti möödumisel ## @@ -729,24 +618,19 @@ away-message-label = .label = ning eemaloleku teateks määratakse: .accesskey = n - send-typing-label = .label = Teist poolt teavitatakse teksti sisestamisest vestlustes .accesskey = T - notification-label = Uue sõnumi saabumisel: - show-notification-label = .label = Teavitusi kuvatakse .accesskey = u - notification-all = .label = koos saatja nime ja sõnumi eelvaatega notification-name = .label = koos saatja nimega notification-empty = .label = ilma lisainfota - notification-type-label = .label = { PLATFORM() -> @@ -758,31 +642,24 @@ [macos] i *[other] V } - chat-play-sound-label = .label = antakse märku heliga .accesskey = h - chat-play-button = .label = Esita .accesskey = E - chat-system-sound-label = .label = süsteemi vaikimisi uue kirja heli .accesskey = s - chat-custom-sound-label = .label = kasutatakse järgnevat helifaili .accesskey = a - chat-browse-sound-button = .label = Lehitse… .accesskey = L - theme-label = .value = Teema: .accesskey = T - style-thunderbird = .label = Thunderbird style-bubbles = @@ -793,14 +670,51 @@ .label = Paberilehed style-simple = .label = Lihtne - preview-label = Eelvaade: no-preview-label = Eelvaade pole saadaval no-preview-description = See teema pole korrektne või pole praegu saadaval (keelatud lisa, ohutu režiim, …). - chat-variant-label = .value = Variant: .accesskey = V +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input = + .style = width: 15.4em + .placeholder = Otsi sätetest ## Preferences UI Search Results +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input2 = + .style = width: 15.4em + .placeholder = Otsi sätetest + +## Settings UI Search Results + +search-results-header = Otsingutulemused +# `` will be replaced by the search term. +search-results-empty-message = + { PLATFORM() -> + [windows] Vabandust! Sätete seast ei leitud vastet otsingule “”. + *[other] Vabandust! Sätete seast ei leitud vastet otsingule “”. + } +# `` will be replaced by the search term. +search-results-empty-message2 = + { PLATFORM() -> + [windows] Vabandust! Sätete seast ei leitud vastet otsingule “”. + *[other] Vabandust! Sätete seast ei leitud vastet otsingule “”. + } +search-results-help-link = Vajad abi? Külasta lehte { -brand-short-name }i abi diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/receipts.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/receipts.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/receipts.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/receipts.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -4,48 +4,35 @@ receipts-dialog-window = .title = Kättesaamise kinnitused - -return-receipt-checkbox = +return-receipt-checkbox-control = .label = Kirjade saatmisel nõutakse alati kättesaamise kinnitust - .acceskey = K - + .accesskey = K receipt-arrive-label = Kui kinnitus saabub: - -receipt-leave-radio = - .label = jäetakse see saabuva posti kausta - .acceskey = j - -receipt-move-radio = +receipt-leave-radio-control = + .label = jäetakse see saabuva e-posti kausta + .accesskey = j +receipt-move-radio-control = .label = tõstetakse see saadetud kirjade kausta - .acceskey = t - + .accesskey = t receipt-request-label = Kui saadakse kättesaamise kinnituse nõue: - -receipt-return-never-radio = +receipt-return-never-radio-control = .label = ei saadeta kunagi vastavat kinnitust - .acceskey = s - -receipt-return-some-radio = + .accesskey = e +receipt-return-some-radio-control = .label = kinnitus lubatakse teatud kirjade korral - .acceskey = l - -receipt-not-to-cc = + .accesskey = k +receipt-not-to-cc-label = .value = kui mind pole kirja või kirja koopia saajate seas: - .acceskey = u - + .accesskey = k receipt-send-never-label = .label = ei saadeta kunagi - receipt-send-always-label = .label = saadetakse alati - receipt-send-ask-label = .label = küsitakse - -sender-outside-domain = +sender-outside-domain-label = .value = kui saajal pole saatjaga sama domeen: - .acceskey = j - -other-cases-label = + .accesskey = d +other-cases-text-label = .value = kõigil muudel juhtudel: - .acceskey = g + .accesskey = j diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/system-integration.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/system-integration.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/preferences/system-integration.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/preferences/system-integration.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -4,16 +4,12 @@ system-integration-title = .title = Süsteemi integratsioon - system-integration-dialog = .buttonlabelaccept = Määra vaikekliendiks .buttonlabelcancel = Jäta vahele .buttonlabelcancel2 = Loobu - default-client-intro = { -brand-short-name }i kasutatakse vaikimisi rakendusena: - unset-default-tooltip = { -brand-short-name }i endaga pole võimalik { -brand-short-name }i vaikekliendi staatust eemaldada. Mõne teise rakenduse vaikekliendiks tegemiseks pead sa kasutama selle rakenduse vastavat funktsionaalsust. - checkbox-email-label = .label = E-postile .tooltiptext = { unset-default-tooltip } @@ -23,7 +19,9 @@ checkbox-feeds-label = .label = Uudistevoogudele .tooltiptext = { unset-default-tooltip } - +checkbox-calendar-label = + .label = Kalender + .tooltiptext = { unset-default-tooltip } # Note: This is the search engine name for all the different platforms. # Platforms that don't support it should be left blank. system-search-engine-name = @@ -32,11 +30,9 @@ [windows] Windows Search *[other] { "" } } - system-search-integration-label = .label = Rakendusel { system-search-engine-name } lubatakse kirju otsida .accesskey = R - check-on-startup-label = .label = See kontroll sooritatakse igal { -brand-short-name }i käivitumisel .accesskey = S diff -Nru thunderbird-91.7.0+build2/l10n/et/mail/messenger/troubleshootMode.ftl thunderbird-91.8.1+build1/l10n/et/mail/messenger/troubleshootMode.ftl --- thunderbird-91.7.0+build2/l10n/et/mail/messenger/troubleshootMode.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/mail/messenger/troubleshootMode.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -2,3 +2,31 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +troubleshoot-mode-window = + .title = { -brand-short-name }i ohutu režiim + .style = width: 37em; +troubleshoot-mode-description = Kasuta { -brand-short-name } ohutut režiimi probleemide diagnoosimiseks. Sinu lisad ja kohendused keelatakse ajutiselt. +troubleshoot-mode-description2 = Sa võid teha mõned või kõik neist muudatustest jäädavaks: +troubleshoot-mode-disable-addons = + .label = Kõik lisad keelatakse + .accesskey = K +troubleshoot-mode-reset-toolbars = + .label = Tööriistaribad ja nupud lähtestatakse + .accesskey = T +troubleshoot-mode-change-and-restart = + .label = Rakenda muudatused ja taaskäivita + .accesskey = R +troubleshoot-mode-continue = + .label = Jätka ohutus režiimis + .accesskey = J +troubleshoot-mode-quit = + .label = + { PLATFORM() -> + [windows] Välju + *[other] Välju + } + .accesskey = + { PLATFORM() -> + [windows] V + *[other] V + } diff -Nru thunderbird-91.7.0+build2/l10n/et/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/et/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/et/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:52:30.000000000 +0000 @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Hele värvilahendus aboutReader.toolbar.colorschemedark = Tume värvilahendus aboutReader.toolbar.colorschemesepia = Seepia värvilahendus +aboutReader.toolbar.colorschemeauto = Automaatne värvilahendus diff -Nru thunderbird-91.7.0+build2/l10n/et/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/et/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/et/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/toolkit/chrome/global/narrate.properties 2022-04-15 07:52:30.000000000 +0000 @@ -9,6 +9,12 @@ back = Tagasi start = Alusta stop = Peata +# %S is the keyboard shortcut for the start command +start-label = Alusta (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Peata (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Liigu edasi speed = Kiirus selectvoicelabel = Hääl: diff -Nru thunderbird-91.7.0+build2/l10n/et/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/et/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/et/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } frame + *[other] { $frames } frames + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } channel + *[other] { $channels } channels + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/et/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/et/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/et/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:40.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/et/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:52:30.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Address Bar: show results during IME composition experimental-features-ime-search-description = An IME (Input Method Editor) is a tool that allows you to enter complex symbols, such as those used in East Asian or Indic written languages, using a standard keyboard. Enabling this experiment will keep the address bar panel open, showing search results and suggestions, while using IME to input text. Note that the IME might display a panel that covers the address bar results, therefore this preference is only suggested for IME not using this type of panel. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name } 100 kasutajaagendi tunnus +experimental-features-firefox-100-description = Seadista { -brand-short-name } saatma veebilehtedele kasutajaagendi tunnust, mis paistab välja nii nagu saiti külastaks { -brand-product-name }i versioon 100. Kasuta seda sätet, et testida, kas saidil tekib probleeme, kui { -brand-short-name } hakkab kandma 3-kohalist versiooninumbrit. Tõeline { -brand-product-name } 100 on ajastatud välja tulema mais 2022, nii et alusta testimist juba praegu! diff -Nru thunderbird-91.7.0+build2/l10n/eu/chat/matrix.properties thunderbird-91.8.1+build1/l10n/eu/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/eu/chat/matrix.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/chat/matrix.properties 2022-04-15 07:52:36.000000000 +0000 @@ -21,7 +21,9 @@ # storage, shown in the account manager. %S is one of the statuses and the # strings are combined with a pipe (|) between. options.encryption.statusOk=Ados +options.encryption.statusNotOk=ez dago prest # %1$S is the session ID, %2$S is the session display name +options.encryption.session=%1$S (%2$S) # LOCALIZATION NOTE (connection.*): # These will be displayed in the account manager in order to show the progress @@ -136,10 +138,14 @@ # %S is the reason string for the particular action. # Used within context of ban, kick and withdrew invite. message.reason=Arrazoia: %S. -# Gets message.reason appended, if a reason was specified. + +# LOCALIZATION NOTE (message.*): +# These are shown as system messages in the conversation. # %1$S is the name of the user who banned. # %2$S is the name of the user who got banned. message.banned=%1$S Kanporatua %2$S. +# Same as message.banned but with a reason. +# %3$S is the reason the user was banned. # %1$S is the name of the user who accepted the invitation. # %2$S is the name of the user who sent the invitation. message.acceptedInviteFor=%1$S %2$S(e)rako gonbidapena onartu du. @@ -167,14 +173,16 @@ # %1$S is the name of the user who unbanned. # %2$S is the name of the user who got unbanned. message.unbanned=%1$S Berronartua %2$S. -# Gets message.reason appended, if a reason was specified. # %1$S is the name of the user who kicked. # %2$S is the name of the user who got kicked. message.kicked=%1$S kanporatua %2$S. -# Gets message.reason appended, if a reason was specified. +# Same as message.kicked but with a third parameter for the reason. +# %3$S is the reason for the kick. # %1$S is the name of the user who withdrew invitation. # %2$S is the name of the user whose invitation has been withdrawn. message.withdrewInvite=%1$SBaztertuen%2$S gonbidapenak. +# Same as message.withdrewInvite but with a third paramter for the reason. +# %3$S is the reason the invite was withdrawn. # %S is the name of the user who has removed the room name. message.roomName.remove=%S Kenduta gelaren izena. # %1$S is the name of the user who changed the room name. @@ -216,3 +224,10 @@ message.alias.removedAndAdded=%1$S(e)k %2$S helbidea ezabatu du eta %3$S gehitu gela honentzat. message.spaceNotSupported=Gela hau euskarririk ez duen tokia da. message.encryptionStart=Elkarrizketa honetako mezuak orain muturretik muturrerako zifratzea dute. +# %1$S is the name of the user who sent the verification request. +# %2$S is the name of the user that is receiving the verification request. +message.verification.request2=%1$S-(e)k %2$S egiaztatu nahi du. +# %1$S is the name of the user who cancelled the verification request. +# %2$S is the reason given why the verification was cancelled. +message.verification.cancel2=%1$S egiaztatzea bertan behera utzi du arrazoi honekin: %2$S +message.verification.done=Egiaztapena burututa. diff -Nru thunderbird-91.7.0+build2/l10n/eu/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/eu/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/eu/devtools/client/compatibility.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/devtools/client/compatibility.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -42,7 +42,14 @@ [one] Bat-etortze { $number } *[other] { $number } bat-etortze } - compatibility-no-issues-found = Ez da bateragarritasun-arazorik aurkitu. compatibility-close-settings-button = .title = Itxi ezarpenak +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Bateragarritasun-arazoak nabigatzaile hauetan: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/eu/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/eu/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/eu/devtools/client/debugger.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/devtools/client/debugger.properties 2022-04-15 07:52:36.000000000 +0000 @@ -642,6 +642,26 @@ ignoreContextItem.unignore=Ez ezikusi iturburua ignoreContextItem.unignore.accesskey=z +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Ezikusi lerroa +ignoreContextItem.ignoreLine.accesskey=l + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Ikusi lerroa +ignoreContextItem.unignoreLine.accesskey=k + +# LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated +# with the ignore lines context menu item +ignoreContextItem.ignoreLines=Ezikusi lerroak +ignoreContextItem.ignoreLines.accesskey=i + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLines): Text associated +# with the unignore lines context menu item +ignoreContextItem.unignoreLines=Ikusi lerroak +ignoreContextItem.unignoreLines.accesskey=u + # LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated # with a mapped source. %S is replaced by the source map origin. sourceFooter.mappedSource=(%S iturburutik) diff -Nru thunderbird-91.7.0+build2/l10n/eu/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/eu/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/eu/devtools/client/netmonitor.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/devtools/client/netmonitor.properties 2022-04-15 07:52:36.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → atzeradeia %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped="%S" karaktere-katea kendu egin da behean erakusten den JSONaren hasieratik + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -855,6 +860,10 @@ # in the action bar's search tab netmonitor.actionbar.search=Bilatu +# LOCALIZATION NOTE (netmonitor.actionbar.HTTPCustomRequest): This is the label displayed +# in the action bar's edit and resend tab +netmonitor.actionbar.HTTPCustomRequest=Eskaera berria + # LOCALIZATION NOTE (messagesTruncated): This is the text displayed # in the messages panel when the number of messages is over the # truncation limit. @@ -1005,6 +1014,10 @@ # in the network toolbar for the search button. netmonitor.toolbar.search=Bilatu +# LOCALIZATION NOTE (netmonitor.toolbar.HTTPCustomRequest): This is the tooltip label displayed +# in the network toolbar for the new HTTP Custom Request button. +netmonitor.toolbar.HTTPCustomRequest=Eskaera berria + # LOCALIZATION NOTE (netmonitor.toolbar.resetColumns): This is the label # displayed in the network table header context menu. netmonitor.toolbar.resetColumns=Berrezarri zutabeak @@ -1452,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Kontsulta-katea: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL parametroak + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Eskaeraren goiburuak: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Goiburuak + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=izena + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=balioa + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Gorputza + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=karga + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Eskaeraren gorputza: @@ -1468,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Utzi +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Garbitu + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Kendu elementua + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Atzera diff -Nru thunderbird-91.7.0+build2/l10n/eu/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/eu/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/eu/devtools/client/toolbox.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/devtools/client/toolbox.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Desgaitu laster-menuak automatikoki ezkutatzea +toolbox-meatball-menu-pseudo-locale-accented = Gaitu "azentudun" hizkuntza +toolbox-meatball-menu-pseudo-locale-bidi = Gaitu "bidi" hizkuntza ## diff -Nru thunderbird-91.7.0+build2/l10n/eu/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/eu/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/eu/devtools/client/toolbox-options.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/devtools/client/toolbox-options.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -42,6 +42,7 @@ options-default-color-unit-hex = Hamaseitarra options-default-color-unit-hsl = HSL(A) options-default-color-unit-rgb = RGB(A) +options-default-color-unit-hwb = HWB options-default-color-unit-name = Koloreen izenak ## Style Editor section @@ -103,6 +104,10 @@ options-enable-remote-label = Gaitu urruneko arazketa options-enable-remote-tooltip2 = .title = Aukera hau aktibatuz gero, nabigatzaile-instantzia hau urrunetik araztu ahal izango da +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Gaitu formateatzaile pertsonalizatuak +options-enable-custom-formatters-tooltip = + .title = Aukera hau gaituz gero, DOM objektuen formateatzaile pertsonalizatuak zehaztu ahal izango dituzte guneek # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Gaitu zerbitzu-langileak HTTP bidez (tresna-kutxa irekita dagoenean) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/eu/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/eu/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/eu/dom/chrome/dom/dom.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/dom/chrome/dom/dom.properties 2022-04-15 07:52:37.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Sartu URL bat. FormValidationInvalidDate=Idatzi baliozko data bat. FormValidationInvalidTime=Idatzi baliozko denbora. +FormValidationInvalidDateTime=Idatzi baliozko data eta denbora. +FormValidationInvalidDateMonth=Idatzi baliozko hilabetea. +FormValidationInvalidDateWeek=Idatzi baliozko astea. FormValidationPatternMismatch=Pareka ezazu eskatutako formatura. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Pareka ezazu eskatutako formatura: %S. @@ -430,3 +433,8 @@ # LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". OffscreenCanvasToBlobWarning=Zaharktituta dago OffscreenCanvas.toBlob(). Erabili OffscreenCanvas.convertToBlob() horren ordez. + +# LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" +IDBDatabaseCreateMutableFileWarning=Zaharkituta dago IDBDatabase.createMutableFile(). API hau estandarizatuko balitz, ziurrenik Origin Private File System esfortzuaren barne izango litzateke: https://bugzil.la/1748667. +# LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" +IDBMutableFileOpenWarning=Zaharkituta dago IDBDatabase.open(). API hau estandarizatuko balitz, ziurrenik Origin Private File System esfortzuaren barne izango litzateke: https://bugzil.la/1748667. diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/browser/appExtensionFields.ftl thunderbird-91.8.1+build1/l10n/eu/mail/browser/appExtensionFields.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/browser/appExtensionFields.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/browser/appExtensionFields.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -5,6 +5,9 @@ ## Theme names and descriptions used in the Themes panel in about:addons +# "Auto" is short for automatic. It can be localized without limitations. +extension-default-theme-name-auto = Sistemaren itxura — automatikoa +extension-default-theme-description = Errespetatu sistema eragilearen ezarpena botoi, menu eta leihoetarako. extension-thunderbird-compact-light-name = Argia extension-thunderbird-compact-light-description = Kolore-eskema argia duen itxura. extension-thunderbird-compact-dark-name = Iluna diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/eu/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/eu/mail/chrome/messenger/addons.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/chrome/messenger/addons.properties 2022-04-15 07:52:36.000000000 +0000 @@ -107,7 +107,6 @@ # %S is brandShortName webextPerms.experimentWarning=Asmo txarreko gehigarriek zure informazio pertsonala lapurtu edo zure ordenagailua arriskuan jar dezakete. Instalatu gehigarri hau iturburu fidagarrikoa bada soilik. - webextPerms.headerWithPerms=%S gehitu? Hedapen honek ondorengo baimenak izango ditu: webextPerms.headerUnsigned=%S gehitu? Hedapen hau egiaztatu gabe dago. Asmo txarreko hedapenek zure informazio pertsonala lapurtu edo zure ordenagailua arriskuan jar dezakete. Instalatu soilik iturburu fidagarrikoa bada. webextPerms.headerUnsignedWithPerms=%S gehitu? Hedapen hau egiaztatu gabe dago. Asmo txarreko hedapenek zure informazio pertsonala lapurtu edo zure ordenagailua arriskuan jar dezakete. Instalatu soilik iturburu fidagarrikoa bada. Hedapen honek ondorengo baimenak izango ditu: @@ -226,6 +225,18 @@ # hosts for which this webextension is requesting permission. webextPerms.hostDescription.tooManySites=Zure datuak beste beste gune batean atzitzea;Zure datuak beste #1 guneetan atzitzea +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextSitePerms.headerWithPerms=%1$S gehitu? Hedapen honek ondorengo gaitasunak ematen dizkio %2$S(r)i: +webextSitePerms.headerUnsignedWithPerms=%1$S gehitu? Hedapen hau egiaztatu gabe dago. Asmo txarreko hedapenek zure informazio pertsonala lapurtu edo zure ordenagailua arriskuan jar dezakete. Instalatu soilik iturburu fidagarrikoa bada. Hedapen honek ondorengo baimenak ematen dizkio %2$S(r)i: + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties +webextSitePerms.description.midi=MIDI gailuak atzitzea +webextSitePerms.description.midi-sysex=SysEx euskarria duten MIDI gailuak atzitzea + # LOCALIZATION NOTE (webext.defaultSearch.description) # %1$S is replaced with the localized named of the extension that is asking to change the default search engine. # %2$S is replaced with the name of the current search engine @@ -235,4 +246,3 @@ webext.defaultSearchYes.accessKey=B webext.defaultSearchNo.label=Ez webext.defaultSearchNo.accessKey=E - diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/chrome/messenger/chat.properties thunderbird-91.8.1+build1/l10n/eu/mail/chrome/messenger/chat.properties --- thunderbird-91.7.0+build2/l10n/eu/mail/chrome/messenger/chat.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/chrome/messenger/chat.properties 2022-04-15 07:52:36.000000000 +0000 @@ -29,6 +29,7 @@ # sends a verification request for end-to-end encryption keys. # %S is replaced with the display name of the user or, if this is to verify a # session of yourself, a string that identifies the session. +buddy.verificationRequest.label=%S(e)k beste identitate guztiak egiaztatu nahi ditu buddy.verificationRequest.allow.label=Hasi egiaztatzea buddy.verificationRequest.allow.accesskey=H buddy.verificationRequest.deny.label=Ukatu diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/aboutImport.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/aboutImport.ftl 2022-04-15 07:52:37.000000000 +0000 @@ -7,12 +7,36 @@ ## Header import-from-app = Inportatu aplikaziotik +import-from-app-desc = Aukeratu inportatzeko Kontuak, Helbide-liburuak, Egutegiak eta bestelako datuak hemendik: +import-address-book = Inportatu helbide-liburu fitxategia +import-calendar = Inportatu egutegi fitxategia ## Buttons +button-cancel = Utzi +button-back = Atzera +button-continue = Jarraitu ## Import from app steps +# Variables: +# $app (String) - The name of the app to import from +profiles-pane-title = Inportatu hemendik { $app } +profiles-pane-desc = Aukeratu inportazio kokapena +profile-file-picker-dir = Aukeratu profil karpeta +profile-file-picker-zip = Aukeratu zip fitxategia (2GB baino txikiagoa) +items-pane-title = Aukeratu zer inportatu +items-pane-desc = Inportatu hemendik +items-pane-checkbox-accounts = Kontu eta ezarpenak +items-pane-checkbox-address-books = Helbide-liburuak +items-pane-checkbox-calendars = Egutegiak +items-pane-checkbox-mail-messages = Posta-mezuak ## Import dialog +progress-pane-title = Inportatzen +progress-pane-restart-desc = Berrabiarazi inportazioa amaitzeko. +error-pane-title = Errorea +error-message-zip-file-too-big = Hautatutako Zip fitxategia 2GB baino handiagoa da. Mesedez, erauzi lehenengo eta gero inportatu erauzitako karpeta. +error-message-extract-zip-file-failed = Huts egin du zip fitxategia erauzteak. Mesedez erauzi eskuz, ondoren inportatu erauzitako karpeta. +error-message-failed = Huts egin du inportazioak ustekabean, informazio gehiago eskuragarri errore kontsolan. diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/aboutRights.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/aboutRights.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/aboutRights.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/aboutRights.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -14,6 +14,7 @@ rights-intro-point-6 = Zenbait bideo-eduki mota erreproduzitu ahal izateko, { -brand-short-name }(e)k edukien deszifratze-modulu zehatz batzuk deskargatzen ditu hirugarrengoengatik. rights-webservices-header = { -brand-full-name } web bidezko informazio-zerbitzuak rights-webservices = { -brand-full-name }(e)k web bidezko informazio-zerbitzuak erabiltzen ditu ("Zerbitzuak") { -brand-short-name }(r)en bertsio bitar honetako funtzionaltasun batzuk hornitzeko, azpian zehaztutako baldintzapean. Ez baduzu Zerbitzu bat edo gehiago erabili nahi edo azpiko baldintzak onargaitzak badira, funtzionaltasuna edo Zerbitzua(k) desgai dezakezu/ditzakezu. Funtzionaltasun konkretuak edo Zerbitzuak desgaitzeko argibideakhemen aurki daitezke. Beste eginbide eta zerbitzuak aplikazioaren hobespenetan desgaitu daitezke. +rights-webservices2 = { -brand-full-name }(e)k web bidezko informazio-zerbitzuak erabiltzen ditu ("Zerbitzuak") { -brand-short-name }(r)en bertsio bitar honetako funtzionaltasun batzuk hornitzeko, azpian zehaztutako baldintzapean. Ez baduzu Zerbitzu bat edo gehiago erabili nahi edo azpiko baldintzak onargaitzak badira, funtzionaltasuna edo Zerbitzua(k) desgai dezakezu/ditzakezu. Funtzionaltasun konkretuak edo Zerbitzuak desgaitzeko argibideakhemen aurki daitezke. Beste eginbide eta zerbitzuak aplikazioaren ezarpenetan desgaitu daitezke. rights-locationawarebrowsing = Kokalekuaren araberako nabigatzea:aukerazkoa da beti. Inoiz ez da kokalekuaren inguruko informaziorik bidaliko zure baimenik gabe. Funtzionaltasuna erabat desgaitu nahi baduzu, jarraitu ondorengo urratsak: rights-locationawarebrowsing-term-1 = URL barran, idatziabout:config rights-locationawarebrowsing-term-2 = Idatzi geo.enabled diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/aboutSupportChat.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/aboutSupportChat.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/aboutSupportChat.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/aboutSupportChat.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -0,0 +1,11 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +chat-title = Txat-kontuak +chat-table-heading-account = ID +chat-table-heading-protocol = Protokoloa +chat-table-heading-name = Izena +chat-table-heading-actions = Ekintzak +chat-table-copy-debug-log = Kopiatu arazketa-loga + .title = Kopiatu txat honetatik erroreak eta bestelako logak arbelera. Informazio pertsonala egon daiteke, adibidez mezuak. diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountCentral.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountCentral.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountCentral.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountCentral.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,58 +4,44 @@ account-central-title = Ongi etorri { -brand-full-name }(e)ra account-settings = Kontu-ezarpenak - # $accounts (Number) - the number of configured accounts setup-title = Aukeratu zer konfiguratu about-title = { -brand-full-name }(r)i buruz resources-title = Baliabideak - release-notes = .title = { -brand-full-name }(r)i buruz - email-label = Helbide elektronikoa .aria-label = konektatu badaukazun posta elektronikora email-description = { -brand-short-name }-(e)k zure posta elektroniko kontua konektatzen uzten dizu, aplikaziotik bertatik egokiro eta eraginkor irakurtzeko zure mezuak. - calendar-label = egutegia .aria-label = Sortu egutegi berri bat calendar-description = { -brand-short-name } antolatua izaten eta zure gertaerak kudeatzen laguntzen dizu. Urruneko egutegi batera konektatuz zure gertaera guztiak zure gailu denetan sinkronizatuak mantenduz. - chat-label = Berriketa .aria-label = Konektatu zure berriketa kontua chat-description = { -brand-short-name } hainbat berehalako mezularitza kontu konektatzen dizu, hainbat plataformei euskarria eskainiz. - filelink-label = Filelink .aria-label = Filelink konfiguratu filelink-description = { -brand-short-name } filelink hodeiko kontua konfiguratzen uzten dizu eranskin handiak modu errazean bidaltzeko. - addressbook-label = Helbide-liburua .aria-label = Sortu Helbide-liburu berria addressbook-description = { -brand-short-name } zure kontaktu guztiak helbide liburuan antolatzen dizkizu. Urrutiko helbide liburu batera ere konekta zintezke zure kontaktu guztiak sinkronizatuta mantentzeko. - feeds-label = Jarioak .aria-label = Jarioetara konektatu feeds-description = { -brand-short-name } RSS/Atom jarioetara konektatzen zaitu berriak eta inguru guztiko eguneratzeak jasotzeko. - newsgroups-label = Berri-taldeak .aria-label = Berri-taldeetara konektatu newsgroups-description = { -brand-short-name } nahi duzun berri-taldeetara konektatzen zaitu. - import-title = Inportatu beste programa batetik… import-paragraph = { -brand-short-name } posta-mezuak, helbide-liburu sarrerak, jario harpidetzak, ezarpenak edota iragazkiak inportatzen dizu beste posta programa batetik eta ohiko helbide-liburu formatuetatik. - +import-paragraph2 = { -brand-short-name } posta-mezuak, helbide-liburu sarrerak, jario harpidetzak, ezarpenak edota iragazkiak inportatzen dizu beste posta programa batetik eta ohiko helbide-liburu formatuetatik. import-label = Inportatu .aria-label = Inportatu datuak beste programa batzuetatik - about-paragraph = Thunderbird da kode irekiko posta eta egutegi bezero plataforma-anitz bakarra, dohakoa negoziorako nahiz erabilera pertsonalerako. Seguru mantendu eta are hobe bilaka dadin nahi dugu. Dohaintzak garatzaileak kontratatzea ahalbidetzen digu, azpiegiturak ordaindu eta hobetzen jarraitu. - about-paragraph-consider-donation = Thunderbird zu bezalako erabiltzaileek diruz mantendua dago! Thunderbird gogoko baduzu, mesedez izan gogoan ekarpen bat egin dezakezula. Biderik onena Thunderbirden etorkizuna ziurtatzeko ekarpena egitea da. - explore-link = Eginbideak esploratu support-link = Laguntza involved-link = Parte hartu developer-link = Garatzaileentzako dokumentazioa - read = Irakurri mezuak compose = Idatzi mezu berria search = Bilatu mezuak diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountcreation/accountSetup.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountcreation/accountSetup.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountcreation/accountSetup.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountcreation/accountSetup.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -7,73 +7,51 @@ ## Header account-setup-title = Ezarri badaukazun posta elektroniko helbide bat - account-setup-description = Zure unekoposta elektroniko helbidea erabiltzeko idatzi zure kredentzialak.
{ -brand-product-name } automatikoki bilatuko du badabiltzan eta gomendatutako zerbitzari konfigurazioa. - account-setup-secondary-description = { -brand-product-name } automatikoki bilatuko du badabilen eta gomendatzen den zerbitzari konfigurazioa. - account-setup-success-title = Kontua ondo sortu da! - account-setup-success-description = Orain zuk { -brand-short-name } kontua erabil dezakezu. - account-setup-success-secondary-description = Esperientzia hobetu dezakezu harremandutako zerbitzuak konektatuz eta konfigurazio aurreratuen ezarpenekin. ## Form fields account-setup-name-label = Zure izen osoa .accesskey = i - # Note: "John Doe" is a multiple-use name that is used when the true name of a person is unknown. We use this fake name as an input placeholder. Translators should update this to reflect the placeholder name of their language/country. account-setup-name-input = .placeholder = Mikel Biteri - account-setup-name-info-icon = .title = Zure izena, besteei erakutsiko zaien bezala - - account-setup-name-warning-icon = .title = { account-setup-name-warning } - account-setup-email-label = Helbide elektronikoa .accesskey = H - account-setup-email-input = .placeholder = mikel.biteri@adibidez.net - account-setup-email-info-icon = .title = Zure posta elektroniko bat - account-setup-email-warning-icon = .title = { account-setup-email-warning } - account-setup-password-label = Pasahitza .accesskey = P .title = Aukerazkoa, erabiltzaile izena egiaztatzeko erabiliko da - account-provisioner-button = Eskuratu posta elektroniko berri bat .accesskey = p - account-setup-password-toggle = .title = Erakutsi/ezkutatu pasahitza - account-setup-password-toggle-show = .title = Erakutsi pasahitza testu garbian - account-setup-password-toggle-hide = .title = Ezkutatu pasahitza - account-setup-remember-password = Gogoratu pasahitza .accesskey = G - account-setup-exchange-label = Zure saio hasiera: .accesskey = s - # YOURDOMAIN refers to the Windows domain in ActiveDirectory. yourusername refers to the user's account name in Windows. account-setup-exchange-input = .placeholder = YOURDOMAIN\zureerabiltzailea - # Domain refers to the Windows domain in ActiveDirectory. We mean the user's login in Windows at the local corporate network. account-setup-exchange-info-icon = .title = Saio domeinua @@ -82,62 +60,39 @@ account-setup-button-cancel = Utzi .accesskey = U - account-setup-button-manual-config = Eskuz konfiguratu .accesskey = k - account-setup-button-stop = Gelditu .accesskey = G - account-setup-button-retest = Birprobatu .accesskey = B - account-setup-button-continue = Jarraitu .accesskey = J - account-setup-button-done = Eginda .accesskey = E ## Notifications account-setup-looking-up-settings = Konfigurazioa bilatzen… - account-setup-looking-up-settings-guess = Konfigurazioa bilatzen: ohiko zerbitzari-izenekin saiatzen - account-setup-looking-up-settings-half-manual = Konfigurazioa bilatzen: zerbitzaria aztertzen - account-setup-looking-up-disk = Konfigurazioa bilatzen: { -brand-short-name } instalazioa… - account-setup-looking-up-isp = Konfigurazioa bilatzen: posta elektronikoaren hornitzailea - # Note: Do not translate or replace Mozilla. It stands for the public project mozilla.org, not Mozilla Corporation. The database is a generic, public domain facility usable by any client. account-setup-looking-up-db = Konfigurazioa bilatzen: Mozilla ISP datu-basea - account-setup-looking-up-mx = Konfigurazioa bilatzen: Sarrera posta domeinua - account-setup-looking-up-exchange = Konfigurazioa bilatzen: Exchange zerbitzaria - account-setup-checking-password = Pasahitza egiaztatzen… - account-setup-installing-addon = Gehigarria deskargatzen eta instalatzen… - account-setup-success-half-manual = Ondorengo ezarpenak aurkitu dira emandako zerbitzaria aztertzean - account-setup-success-guess = Konfigurazioa aurkitu da ohiko zerbitzari-izenekin saiatzean - account-setup-success-guess-offline = Lineaz kanpo zaude. Ustez zenbait ezarpen igarri ditugu baina ezarpen egokiak sartu beharko dituzu. - account-setup-success-password = Pasahitz zuzena - account-setup-success-addon = Gehigarria ondo instalatu da. - # Note: Do not translate or replace Mozilla. It stands for the public project mozilla.org, not Mozilla Corporation. The database is a generic, public domain facility usable by any client. account-setup-success-settings-db = Konfigurazioa aurkitu da Mozilla ISP datu-basean - account-setup-success-settings-disk = Konfigurazioa aurkitu da { -brand-short-name } instalazioan. - account-setup-success-settings-isp = Konfigurazioa aurkitu da posta elektronikoaren hornitzailean. - # Note: Microsoft Exchange is a product name. account-setup-success-settings-exchange = Microsoft Exchange zerbitzarirako konfigurazioa aurkitua. @@ -145,33 +100,21 @@ account-setup-step1-image = .title = Hasierako konfigurazioa - account-setup-step2-image = .title = Kargatzen… - account-setup-step3-image = .title = Konfigurazioa aurkitua - account-setup-step4-image = .title = Konexio errorea - account-setup-step5-image = .title = Kontua sortua - account-setup-privacy-footnote2 = Zure kredentzialak lokalean bakarrik, zure ordenagailuan, gordeko dira - account-setup-selection-help = Ez dakizu zer hautatu? - account-setup-selection-error = Laguntza bila? - account-setup-success-help = Ez dakizu zeintzuk diren hurrengo urratsak? - account-setup-documentation-help = Konfigurazio dokumentazioa - account-setup-forum-help = Laguntza foroa - account-setup-privacy-help = Pribatutasun-politika - account-setup-getting-started = Nola hasi ## Results area @@ -183,41 +126,25 @@ [one] Konfigurazio erabilgarria *[other] Konfigurazio erabilgarriak } - # Note: IMAP is the name of a protocol. account-setup-result-imap = IMAP - account-setup-result-imap-description = Mantendu zure karpetak eta postak sinkronizatuak zure zerbitzarian - # Note: POP3 is the name of a protocol. account-setup-result-pop = POP3 - account-setup-result-pop-description = Mantendu zure karpetak eta postak zure konputagailuan - # Note: Exchange is the name of a product. account-setup-result-exchange = Exchange - # Note: Exchange, Office365 are the name of products. account-setup-result-exchange2-description = Erabili Microsoft Exchange server edo Office365 cloud zerbitzuak - account-setup-incoming-title = Sarrerakoa - account-setup-outgoing-title = Irteerakoa - account-setup-username-title = Erabiltzaile-izena - account-setup-exchange-title = Zerbitzaria - account-setup-result-smtp = SMTP - account-setup-result-no-encryption = Zifraketarik ez - account-setup-result-ssl = SSL/TLS - account-setup-result-starttls = STARTTLS - account-setup-result-outgoing-existing = Erabili badagoen irteerako SMTP zerbitzaria - # Variables: # $incoming (String): The email/username used to log into the incoming server # $outgoing (String): The email/username used to log into the outgoing server @@ -227,81 +154,55 @@ # Note: The reference to "janedoe" (Jane Doe) is the name of an example person. You will want to translate it to whatever example persons would be named in your language. In the example, AD is the name of the Windows domain, and this should usually not be translated. account-setup-credentials-incomplete = Autentifikazioak huts egin du.Edo sartutako kredentzialak ez dira zuzenak edo aparteko erabiltzaile-izena behar da saioa hasteko. Erabiltzaile-izen hau normalean zure windows domeinuko saiokoa izaten da domeinuaz edo domeinu gabe (Adibidez, mikeltxo edo AD\\mikeltxo). - account-setup-credentials-wrong = Autentifikazioak huts egin du. Mesedez berrikusi erabiltzaile izena eta pasahitza. - account-setup-find-settings-failed = { -brand-short-name }(e)k ez du zure posta-kontuaren ezarpenik aurkitu. - account-setup-exchange-config-unverifiable = Konfigurazioa ezin da egiaztatu. Zure erabiltzaile izena eta pasahitza zuzenak badira, litekeena da zerbitzari administratzaileak zure konturako aukeratutako konfigurazioa desgaitu izana. Saiatu beste protokolo bat aukeratuz. +account-setup-provisioner-error = Errorea eman { -brand-short-name }(e)n zure kontu berria ezartzean. Mesedez, saiatu eskuz ezartzen zure kontua zure kredentzialekin. ## Manual configuration area account-setup-manual-config-title = Zerbitzariaren ezarpenak - account-setup-incoming-server-legend = Hartzeko zerbitzaria - account-setup-protocol-label = Protokoloa: - protocol-imap-option = { account-setup-result-imap } - protocol-pop-option = { account-setup-result-pop } - protocol-exchange-option = { account-setup-result-exchange } - account-setup-hostname-label = Ostalari-izena: - account-setup-port-label = Ataka: .title = ezarri ataka zenbakia 0 autodetektatzeko - account-setup-auto-description = { -brand-short-name } hutsik dauden eremuak auto-detektatzen saiatuko da. - account-setup-ssl-label = Konexioaren segurtasuna: - account-setup-outgoing-server-legend = Posta bidaltzeko zerbitzaria ## Incoming/Outgoing SSL Authentication options ssl-autodetect-option = Autodetektatu - ssl-no-authentication-option = Autentifikaziorik ez - ssl-cleartext-password-option = Pasahitz arrunta - ssl-encrypted-password-option = Zifratutako pasahitza ## Incoming/Outgoing SSL options ssl-noencryption-option = Bat ere ez - account-setup-auth-label = Autentifikazio metodoa: - account-setup-username-label = Erabiltzaile-izena: - account-setup-advanced-setup-button = Konfigurazio aurreratua .accesskey = a ## Warning insecure server dialog account-setup-insecure-title = Kontuz! - account-setup-insecure-incoming-title = Hartzeko ezarpenak: - account-setup-insecure-outgoing-title = Irteerako ezarpenak: - # Variables: # $server (String): The name of the hostname of the server the user was trying to connect to. account-setup-warning-cleartext = { $server } ez du zifratzerik erabiltzen. - account-setup-warning-cleartext-details = Posta-zerbitzari ez-seguruek ez dute zifratutako konexiorik erabiltzen zure pasahitz eta informazio pribatua babesteko. Konexio honetara konektatuz gero, zure pasahitz eta informazio pribatua agerian gera daiteke. - account-setup-insecure-server-checkbox = Arriskuak ulertzen ditut. .accesskey = u - account-setup-insecure-description = { -brand-short-name }(e)k dakartzan konfigurazioekin zure posta eskura dezakezu. Halere, zure administrariaz edo posta hornitzaileaz jarri beharko zenuke harremanetan. Ikusi Thunderbirden FAQ argibide gehiagorako. - insecure-dialog-cancel-button = Aldatu ezarpenak .accesskey = e - insecure-dialog-confirm-button = Berretsi .accesskey = B @@ -310,66 +211,45 @@ # Variables: # $domain (String): The name of the server where the configuration was found, e.g. rackspace.com. exchange-dialog-question = { -brand-short-name } zure kontuko ezarpenak aurkitu ditu hemen: { $domain }. Jarraitu nahi duzu eta zure kredentzialak aurkeztu? - exchange-dialog-confirm-button = Saio-hasiera - exchange-dialog-cancel-button = Utzi ## Dismiss account creation dialog exit-dialog-title = Ez dago posta helbiderik konfiguratua - exit-dialog-description = Ziur zaude konfigurazioa prozesua bertan behera utzi nahi duzula? { -brand-short-name } posta elektroniko helbide gabe erabili daiteke, baina hainbat eginbide ez dira eskuragarri egongo. - account-setup-no-account-checkbox = Erabili { -brand-short-name } posta elektroniko kontu gabe .accesskey = E - exit-dialog-cancel-button = Jarraitu konfigurazioa .accesskey = J - exit-dialog-confirm-button = Irten konfiguraziotik .accesskey = I ## Alert dialogs account-setup-creation-error-title = Errorea kontua sortzean - account-setup-error-server-exists = Hartzeko zerbitzaria dagoeneko badago. - account-setup-confirm-advanced-title = Konfigurazio aurreratua berretsi - account-setup-confirm-advanced-description = Elkarrizketa koadro hau itxiko da eta kontua sortuko da oraingo ezarpenekin, akastun konfigurazioa bada ere. Aurrera jo nahi duzu? ## Addon installation section account-setup-addon-install-title = Instalatu - account-setup-addon-install-intro = Hirugarren baten gehigarriak ahalbidetu diezazuke sarbidea zure posta elektronikoari zerbitzari honetan: - account-setup-addon-no-protocol = Posta zerbitzariak zoritzarrez ez ditu onartzen protokolo irekiak. { account-setup-addon-install-intro } ## Success view account-setup-settings-button = Kontu-ezarpenak - account-setup-encryption-button = Muturretik muturrerako enkriptatzea - account-setup-signature-button = Gehitu sinadura - account-setup-dictionaries-button = Deskargatu hiztegiak - account-setup-address-book-carddav-button = CardDAV helbide-liburura konektatu - account-setup-address-book-ldap-button = LDAP helbide-liburura konektatu - account-setup-calendar-button = Konektatu urruneko egutegira - account-setup-linked-services-title = Konektatu zure lotutako zerbitzuekin - account-setup-linked-services-description = { -brand-short-name } zure postaz lotutako zerbitzu gehiago antzeman ditu. - account-setup-no-linked-description = Konfiguratu beste zerbitzuak zure { -brand-short-name } esperientziari ahalik eta etekin handiena ateratzeko. - # Variables: # $count (Number) - The number of address books found during autoconfig. account-setup-found-address-books-description = @@ -377,7 +257,6 @@ [one] { -brand-short-name } zure postari lotutako helbide liburu bat aurkitu du. *[other] { -brand-short-name } zure postari lotutako { $count } helbide liburu aurkitu ditu. } - # Variables: # $count (Number) - The number of calendars found during autoconfig. account-setup-found-calendars-description = @@ -385,62 +264,41 @@ [one] { -brand-short-name } zure postari lotutako egutegi bat aurkitu du. *[other] { -brand-short-name } zure postari lotutako { $count } egutegi aurkitu ditu. } - account-setup-button-finish = Amaitu .accesskey = A - account-setup-looking-up-address-books = Helbide-liburuak bilatzen… - account-setup-looking-up-calendars = Egutegiak bilatzen… - account-setup-address-books-button = Helbide-liburuak - account-setup-calendars-button = Egutegiak - account-setup-connect-link = Konektatu - account-setup-existing-address-book = Konektatuta .title = Helbide-liburua konektatua dago - account-setup-existing-calendar = Konektatuta .title = Egutegia konektatua dago - account-setup-connect-all-calendars = Konektatu egutegi guztiak - account-setup-connect-all-address-books = Konektatu helbide-liburu guztiak ## Calendar synchronization dialog calendar-dialog-title = Konektatu egutegia - calendar-dialog-cancel-button = Utzi .accesskey = U - calendar-dialog-confirm-button = Konektatu .accesskey = K - account-setup-calendar-name-label = Izena - account-setup-calendar-name-input = .placeholder = Nire egutegia - account-setup-calendar-color-label = Kolorea - account-setup-calendar-refresh-label = Berritu - account-setup-calendar-refresh-manual = Eskuz - account-setup-calendar-refresh-interval = { $count -> [one] Minutuoro *[other] { $count } minututik behin } - account-setup-calendar-read-only = irakurtzeko soilik .accesskey = s - account-setup-calendar-show-reminders = Erakutsi gogorarazleak .accesskey = g - account-setup-calendar-offline-support = Lineaz kanpoko laguntza .accesskey = L diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountManager.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountManager.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountManager.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountManager.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -3,6 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. open-preferences-sidebar-button = { -brand-short-name } hobespenak +open-preferences-sidebar-button2 = { -brand-short-name } ezarpenak open-addons-sidebar-button = Gehigarriak eta itxurak account-action-add-newsgroup-account = .label = Gehitu berri-talde kontua… diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountProvisioner.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountProvisioner.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/accountProvisioner.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/accountProvisioner.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -2,5 +2,30 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +account-provisioner-tab-title = Lortu posta elektroniko helbide berria zerbitzu hornitzaile batengandik provisioner-searching-icon = .alt = Bilatzen… +account-provisioner-title = Sortu posta elektroniko berri bat +account-provisioner-mail-account-title = Erosi posta elektroniko berri bat +account-provisioner-domain-title = Erosi posta helbidea eta domeinua zuretzat + +## Forms + +account-provisioner-search-button = Bilatu +account-provisioner-button-cancel = Utzi +account-provisioner-button-existing = Ezarri baduzun posta elektroniko kontu bat +account-provisioner-button-back = Joan atzera + +## Notifications + + +## Illustrations + + +## Search results + +account-provisioner-free-account = Doan +account-provision-price-per-year = { $price } urtean +account-provisioner-all-results-button = Erakutsi emaitza guztiak +account-provisioner-open-in-tab-img = + .title = Ireki fitxa berri batean diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = CardDAV helbide-liburu berria - +carddav-window-title = CardDAV helbide-liburu berria carddav-dialog = .buttonlabelaccept = Jarraitu .buttonaccesskeyaccept = J - carddav-username-label = .value = Erabiltzailea: .accesskey = E - carddav-location-label = .value = Kokapena: .accesskey = K carddav-location = .default-placeholder = Helbide liburuaren URL edo ostalari izena - carddav-loading = Konfigurazioa bilatzen… carddav-known-incompatible = { $url } eta { -brand-short-name } bateragarriak ez direla ezaguna da. carddav-connection-error = Huts konektatzerakoan. carddav-none-found = Ez da helbide-libururik aurkitu gehitzeko zehaztutako kontuan. carddav-already-added = Zehaztutako kontuko helbide-liburu guztiak gehitu dira. - carddav-available-books = Helbide-liburu eskuragarriak diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -16,22 +16,26 @@ .label = Kontaktu berria about-addressbook-toolbar-new-list = .label = Zerrenda berria +about-addressbook-toolbar-import = + .label = Inportatu ## Books all-address-books = Helbide-liburu guztiak - about-addressbook-books-context-properties = .label = Propietateak about-addressbook-books-context-synchronize = .label = Sinkronizatu about-addressbook-books-context-print = .label = Inprimatu… +about-addressbook-books-context-export = + .label = Esportatu… about-addressbook-books-context-delete = .label = Ezabatu about-addressbook-books-context-remove = .label = Kendu - +about-addressbook-books-context-startup-default = + .label = Abio direktorio lehenetsia about-addressbook-confirm-delete-book-title = Ezabatu helbide-liburua # Variables: # $name (String) - Name of the address book to be deleted. @@ -49,17 +53,14 @@ .placeholder = Bilatu { $name } about-addressbook-search-all = .placeholder = Bilatu helbide-liburu guztiak - about-addressbook-sort-button = .title = Aldatu zerrenda ordena - about-addressbook-name-format-display = .label = Bistaratzeko izena about-addressbook-name-format-firstlast = .label = Izena, abizena about-addressbook-name-format-lastfirst = .label = Abizena, izena - about-addressbook-sort-name-ascending = .label = Ordenatu izenaz (A > Z) about-addressbook-sort-name-descending = @@ -68,10 +69,8 @@ .label = Ordenatu Eposta helbideaz (A > Z) about-addressbook-sort-email-descending = .label = Ordenatu Eposta helbideaz (Z > A) - about-addressbook-cards-context-write = .label = Idatzi - about-addressbook-confirm-delete-mixed-title = Ezabatu kontaktuak eta posta-zerrendak # Variables: # $count (Number) - The number of contacts and lists to be deleted. Always greater than 1. @@ -128,9 +127,17 @@ about-addressbook-begin-edit-contact-button = Editatu about-addressbook-cancel-edit-contact-button = Utzi about-addressbook-save-edit-contact-button = Gorde - about-addressbook-details-email-addresses-header = Helbide elektronikoak about-addressbook-details-phone-numbers-header = Telefono zenbakiak about-addressbook-details-home-address-header = Etxeko helbidea about-addressbook-details-work-address-header = Laneko helbidea about-addressbook-details-other-info-header = Bestelako informazioa + +# Photo dialog + +about-addressbook-photo-drop-loading = Argazkia kargatzen… +about-addressbook-photo-drop-error = Huts egin du argazkia kargatzeak. +about-addressbook-photo-filepicker-title = Hautatu irudi-fitxategia +about-addressbook-photo-discard = Baztertu dagoen argazkia +about-addressbook-photo-cancel = Utzi +about-addressbook-photo-save = Gorde diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/addressbook/fieldMapImport.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/addressbook/fieldMapImport.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/addressbook/fieldMapImport.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/addressbook/fieldMapImport.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,10 +4,9 @@ import-ab-csv-window = .title = Inportatu helbide-liburua testu fitxategitik - +import-ab-csv-dialog-title = Inportatu helbide-liburua testu fitxategitik # $recordNumber (Number) - The current record number of the preview data. import-ab-csv-preview-record-number = { $recordNumber } erregistroaren datu inportazioaren aurrebista. - import-ab-csv-dialog = .buttonlabelaccept = Inportatu .buttonaccesskeyaccept = I diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/chat.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/chat.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/chat.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/chat.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,18 +4,29 @@ chat-joining-chat-icon2 = .alt = Txatera batzen - chat-left-chat-icon2 = .alt = Utzi txata - chat-participant-owner-role-icon2 = .alt = Jabea - chat-participant-administrator-role-icon2 = .alt = Administratzailea - chat-participant-moderator-role-icon2 = .alt = Moderatzailea - chat-participant-voiced-role-icon2 = .alt = Partaideak mezuak bidal ditzake +chat-verify-identity = + .label = Egiaztatu identitatea + .accesskey = i +chat-identity-verified = + .label = Identitatea jada egiaztatua +chat-buddy-identity-status-verified = Egiaztatuta +chat-buddy-identity-status-unverified = Egiaztatu gabea + +## Conversation invite notification box + +chat-conv-invite-accept = + .label = Onartu + .accesskey = O +chat-conv-invite-deny = + .label = Baztertu + .accesskey = B diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/chat-verifySession.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/chat-verifySession.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/chat-verifySession.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/chat-verifySession.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -0,0 +1,13 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +verify-window-title = Egiaztatu identitatea +# Variables: +# $subject (String) - a human readable identifier for the other side of the verification flow. +verify-window-subject-title = Egiaztatu { $subject }(e)n identitatea +verify-dialog = + .buttonlabelaccept = Bat datoz + .buttonaccesskeyaccept = B + .buttonlabelextra2 = Ez datoz bat + .buttonaccesskeyextra2 = E diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/exportDialog.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/exportDialog.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/exportDialog.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/exportDialog.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -3,21 +3,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export-dialog-brand-name = { -brand-product-name } - -export-dialog-window = - .title = Esportatu - +export-dialog-title = Esportatu export-dialog = .buttonlabelaccept = Hurrengoa - export-dialog-button-finish = Amaitu - export-dialog-file-picker = Esportatu zip fitxategira - -export-dialog-desc1 = Esportatu posta kontuak, posta mezuak, helbide-liburuak, hobespenak zip fitxategira. - +export-dialog-description1 = Esportatu posta kontuak, posta mezuak, helbide-liburuak, ezarpenak zip fitxategira. export-dialog-desc2 = Behar duzunean, zip fitxategia inportatu ahal duzu zure profila berreskuratzeko. - export-dialog-exporting = Esportatzen… - export-dialog-exported = Esportatua! diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/menubar.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/menubar.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -2,6 +2,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +toolbar-context-menu-menu-bar = + .toolbarname = Menu-barra + .accesskey = M ## Tools Menu @@ -10,6 +13,9 @@ menu-tools-preferences = .label = Hobespenak .accesskey = H +menu-tools-settings = + .label = Ezarpenak + .accesskey = E menu-addons-and-themes = .label = Gehigarriak eta itxurak .accesskey = G diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -3,7 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Addressing widget +## Addressing widget # $type (String) - the type of the addressing row remove-address-row-button = @@ -43,7 +43,7 @@ .label = Zabaldu zerrenda .accesskey = Z -# Attachment widget +## Attachment widget ctrl-cmd-shift-pretty-prefix = { PLATFORM() -> @@ -98,7 +98,7 @@ *[other] Erakutsi barnekoak } -# Reorder Attachment Panel +## Reorder Attachment Panel move-attachment-first-panel-button = .label = Mugi lehenera @@ -112,14 +112,14 @@ .label = Hartu-agiria .tooltiptext = Eskatu hartu-agiria mezu honetarako -# Encryption +## Encryption message-to-be-signed-icon = .alt = Sinatu mezua message-to-be-encrypted-icon = .alt = Zifratu mezua -# Addressing Area +## Addressing Area to-compose-address-row-label = .value = Nori @@ -237,3 +237,20 @@ compose-tool-button-remove-text-styling = .tooltiptext = Kendu testu estiloak + +## FileLink + + +# Template + +cloud-file-template-size = Tamaina: +cloud-file-template-link = Lotura: +cloud-file-template-expiry-date = Iraungitze data: + +# Messages + +# $provider (string) - name of the online storage service that reported the error +cloud-file-connection-error-title = Konexio errorea +# $provider (string) - name of the online storage service that reported the error +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-rename-error-title = Errorea izena aldatzean diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/messenger.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/messenger.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -2,6 +2,17 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +## Window controls + +messenger-window-minimize-button = + .tooltiptext = Txikitu +messenger-window-maximize-button = + .tooltiptext = Maximizatu +messenger-window-restore-down-button = + .tooltiptext = Leheneratu txikira +messenger-window-close-button = + .tooltiptext = Itxi # Variables: # $count (Number) - Number of unread messages. unread-messages-os-tooltip = @@ -9,7 +20,6 @@ [one] Irakurri gabeko mezu 1 *[other] { $count } mezu irakurri gabe } - about-rights-notification-text = { -brand-short-name } kode irekikoa eta software librea da, munduan zehar milaka kide dituen komunitateak egina. ## Content tabs @@ -26,11 +36,9 @@ addons-and-themes-toolbarbutton = .label = Gehigarriak eta itxurak .tooltiptext = Kudeatu zure gehigarriak - quick-filter-toolbarbutton = .label = Iragazki bizkorra .tooltiptext = Iragazi mezuak - redirect-msg-button = .label = Birbideratzea .tooltiptext = Birbideratu hautatutako mezua @@ -40,10 +48,8 @@ folder-pane-toolbar = .toolbarname = Karpeten panelaren tresna-barra .accesskey = K - folder-pane-toolbar-options-button = .tooltiptext = Karpeten panelaren aukerak - folder-pane-header-label = Karpetak ## Folder Toolbar Header Popup @@ -51,27 +57,21 @@ folder-toolbar-hide-toolbar-toolbarbutton = .label = Ezkutatu tresna-barra .accesskey = E - show-all-folders-label = .label = Karpeta guztiak .accesskey = K - show-unread-folders-label = .label = Irakurri gabeko karpetak .accesskey = I - show-favorite-folders-label = .label = Gogoko karpetak .accesskey = G - show-smart-folders-label = .label = Elkartutako karpetak .accesskey = E - show-recent-folders-label = .label = Azken karpetak .accesskey = A - folder-toolbar-toggle-folder-compact-view = .label = Ikuspegi trinkoa .accesskey = t @@ -81,6 +81,9 @@ redirect-msg-menuitem = .label = Birbideratzea .accesskey = B +menu-file-save-as-file = + .label = Fitxategia… + .accesskey = F ## AppMenu @@ -88,19 +91,18 @@ # and consolidated everything with Preferences. appmenu-preferences = .label = Hobespenak - +appmenu-save-as-file = + .label = Fitxategia… +appmenu-settings = + .label = Ezarpenak appmenu-addons-and-themes = .label = Gehigarriak eta itxurak - appmenu-help-enter-troubleshoot-mode = .label = Arazoak konpontzeko modua… - appmenu-help-exit-troubleshoot-mode = .label = Desaktibatu arazoak konpontzeko modua - appmenu-help-more-troubleshooting-info = .label = Arazoak konpontzeko informazio gehiago - appmenu-redirect-msg = .label = Birbideratzea @@ -108,11 +110,23 @@ context-menu-redirect-msg = .label = Birbideratzea +mail-context-delete-messages = + .label = + { $count -> + [one] Ezabatu mezua + *[other] Ezabatu hautatutako mezuak + } ## Message header pane other-action-redirect-msg = .label = Birbideratzea +message-header-msg-flagged = + .title = Izarduna + .aria-label = I +message-header-msg-not-flagged = + .title = Izarrik gabeak + .aria-label = g ## Action Button Context Menu @@ -127,7 +141,6 @@ message-header-address-in-address-book-icon = .alt = Helbidea helbide-liburuan dago - message-header-address-not-in-address-book-icon = .alt = Helbidea ez dago helbide-liburuan @@ -138,11 +151,9 @@ addon-removal-title = { $name } kendu? addon-removal-confirmation-button = Kendu addon-removal-confirmation-message = Kendu { $name } eta bere konfigurazio eta datuak { -brand-short-name }(e)tik? - caret-browsing-prompt-title = Kurtsore bidezko nabigazioa caret-browsing-prompt-text = F7 zapaltzeak kurtsore bidezko nabigazioa gaitzen edo desgaitzen du. Eginbide honek zenbait edukitan kurtsore bat ezartzen du testua teklatuarekin aukeratzea baimenduz. Kurtsore bidezko nabigazioa gaitu nahi duzu? caret-browsing-prompt-check-text = Ez galdetu berriz. - repair-text-encoding-button = .label = Konpondu testu kodeketa .tooltiptext = Testuaren kodeketa zuzena asmatu mezuaren edukian oinarrituz @@ -152,3 +163,21 @@ no-reply-title = Ezin da erantzun no-reply-message = Erantzuneko posta helbidea ({ $email }) ez dirudi inork kontrolatutakoa. Litekeena da bertara idatzitako mezuak inork ez irakurtzea. no-reply-reply-anyway-button = Erantzun hala ere + +## error messages + + +## Spaces toolbar + +spaces-toolbar-button-mail = + .title = Aldatu posten fitxara +spaces-toolbar-button-address-book = + .title = Aldatu helbide-liburu fitxara +spaces-toolbar-button-calendar = + .title = Aldatu egutegiaren fitxara +spaces-toolbar-button-tasks = + .title = Aldatu zereginen fitxara +spaces-toolbar-button-chat = + .title = Aldatu txat fitxara +spaces-toolbar-button-settings = + .title = Aldatu ezarpenen fitxara diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/otr/otrUI.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/otr/otrUI.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -6,86 +6,60 @@ refresh-label = Freskatu zifratutako elkarrizketa auth-label = Egiaztatu zure kontaktuaren identitatea reauth-label = berriz egiaztatu zure kontaktuaren identitatea - auth-cancel = Utzi auth-cancel-access-key = U - auth-error = Errorea izan da zure kontaktuaren identitatea egiaztatzerakoan. auth-success = Zure kontaktuen identitatearen egiaztapena ondo burutu da. auth-success-them = Zure kontaktuak zure identitatea ondo egiaztatu du. Beharbada zuk bere identitatea egiaztatu nahi izango duzu zure galdera eginaz. auth-fail = Zure kontaktuaren identitatea egiaztatzeak huts egin du. auth-waiting = Kontaktuaren zain egiaztapena burutzeko… - finger-verify = Egiaztatu finger-verify-access-key = E - +finger-ignore = Ezikusi +finger-ignore-access-key = E # Do not translate 'OTR' (name of an encryption protocol) buddycontextmenu-label = Gehitu OTR hatz-marka - # Variables: # $name (String) - the screen name of a chat contact person alert-start = { $name }(e)kin zifratutako elkarrizketa abiarazten. - # Variables: # $name (String) - the screen name of a chat contact person alert-refresh = { $name }(e)kin zifratutako elkarrizketa freskatzen. - # Variables: # $name (String) - the screen name of a chat contact person alert-gone-insecure = { $name }(e)kin zifratutako elkarrizketa amaitu da. - # Variables: # $name (String) - the screen name of a chat contact person finger-unseen = { $name }(e)n identitatea ezin izan da egiaztatu oraindik. Ustegabeko entzuteak ez dira posible, baina ahalegin batekin inor entzuten egon liteke. Ekidin begiraleak kontaktuen identitatea egiaztatuz. - # Variables: # $name (String) - the screen name of a chat contact person finger-seen = { $name } zurekin kontaktatzen ari da ordenagailu ezezagun batetik. Ustegabeko entzuteak ez dira posible, baina ahalegin batekin inor entzuten egon liteke. Ekidin begiraleak kontaktuen identitatea egiaztatuz. - state-not-private = Uneko elkarrizketa ez da pribatua. - state-generic-not-private = Uneko elkarrizketa ez da pribatua. - # Variables: # $name (String) - the screen name of a chat contact person state-unverified = Uneko elkarrizketa zifratua dago baina ez da pribatua, { $name }(e)n identitatea oraindik ez baita egiaztatu. - state-generic-unverified = Uneko elkarrizketa zifratua dago baina ez da pribatua, hainbat identitate oraindik ez baitira egiaztatu. - # Variables: # $name (String) - the screen name of a chat contact person state-private = { $name }(e)n identitatea egiaztatu da. Elkarrizketa zifratua eta pribatua da. - state-generic-private = Uneko elkarrizketa zifratua eta pribatua da. - # Variables: # $name (String) - the screen name of a chat contact person state-finished = { $name }(e)k elkarrizketa zifratua amaitu du zurekin, zuk berdin egin beharko zenuke. - state-not-private-label = Ez-seguru state-unverified-label = Egiaztatu gabea state-private-label = Pribatua state-finished-label = Amaituta - # Variables: # $name (String) - the screen name of a chat contact person verify-request = { $name }(e)k zure identitatea egiaztatzea eskatu du. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-private = { $name }(e)n identitatea egiaztatu duzu. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-unverified = { $name }(e)n identitatea ez da egiaztatu. - -verify-title = Egiaztatu zure kontaktuaren identitatea -error-title = Errorea -success-title = Muturretik muturrerako enkriptatzea -success-them-title = Egiaztatu zure kontaktuaren identitatea -fail-title = Ezin da egiaztatu -waiting-title = Egiaztapen eskaria bidalita - # Do not translate 'OTR' (name of an encryption protocol) # Variables: # $error (String) - contains an error message that describes the cause of the failure diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/am-im.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/am-im.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/am-im.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/am-im.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,6 +4,10 @@ account-settings-title = Autentifikazio ezarpenak account-channel-title = Kanal lehenetsiak +chat-autologin = + .label = Hasi saioa abioan +chat-encryption-generic = Orokorra +chat-encryption-status = Zifratze egoera chat-encryption-sessions = Saioak chat-encryption-session-verify = Egiaztatu .title = Egiaztatu saio honen indentitatea diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/connection.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/connection.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/connection.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/connection.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,20 +4,16 @@ connection-dns-over-https-url-resolver = Erabili hornitzailea .accesskey = h - # Variables: # $name (String) - Display name or URL for the DNS over HTTPS provider connection-dns-over-https-url-item-default = .label = { $name }(lehenetsia) .tooltiptext = Erabili URL lehenetsia HTTPSn DNSak ebazteko - connection-dns-over-https-url-custom = .label = Pertsonalizatua .accesskey = P .tooltiptext = Sartu zure gogoko URL HTTPSn DNSak ebazteko - connection-dns-over-https-custom-label = Pertsonalizatua - connection-dialog-window = .title = Konexio-ezarpenak .style = @@ -25,90 +21,74 @@ [macos] width: 44em !important *[other] width: 49em !important } - connection-disable-extension = .label = Desgaitu hedapena - +disable-extension-button = Desgaitu hedapena +# Variables: +# $name (String) - The extension that is controlling the proxy settings. +# +# The extension-icon is the extension's icon, or a fallback image. It should be +# purely decoration for the actual extension name, with alt="". +proxy-settings-controlled-by-extension = { $name } hedapenak, kontrolatzen du { -brand-short-name } internetera nola konektatzen den. connection-proxy-legend = Konfiguratu Internet atzitzeko proxy-ak - proxy-type-no = .label = Proxy-rik ez .accesskey = y - proxy-type-wpad = .label = Automatikoki detektatu sare honetako proxy-ezarpenak .accesskey = s - proxy-type-system = .label = Erabili sistemaren proxy-ezarpenak .accesskey = E - proxy-type-manual = .label = Eskuzko proxy-konfigurazioa: .accesskey = s - proxy-http-label = .value = HTTP proxy-a: .accesskey = H - http-port-label = .value = Ataka: .accesskey = k - proxy-http-sharing = .label = Erabili proxy hau HTTPS protokoloarentzat ere bai .accesskey = x - proxy-https-label = .value = HTTP proxy-a: .accesskey = S - ssl-port-label = .value = Ataka: .accesskey = A - proxy-socks-label = .value = SOCKS ostalaria: .accesskey = C - socks-port-label = .value = Ataka: .accesskey = t - proxy-socks4-label = .label = SOCKS v4 .accesskey = K - proxy-socks5-label = .label = SOCKS v5 .accesskey = v - proxy-type-auto = .label = Proxy-aren konfigurazio automatikoko URLa: .accesskey = a - proxy-reload-label = .label = Berritu .accesskey = B - no-proxy-label = .value = Proxy-rik ez hauentzat: .accesskey = n - no-proxy-example = Adibidez: .mozilla.org, .net.nz, 192.168.1.0/24 - # Do not translate "localhost", "127.0.0.1/8" and "::1". (You can translate "and".) connection-proxy-noproxy-localhost-desc-2 = localhost, 127.0.0.1/8 eta ::1 helbideetarako konexioak inoiz ez dira proxy bidez egiten. - proxy-password-prompt = .label = Ez eskatu autentifikaziorik pasahitza gordeta badago .accesskey = i .tooltiptext = Aukera honek proxietarako autentifikazioa isilean burutzen du hauentzat kredentzialak gorde dituzunean. Autentifikazioak huts egiten badu, eskatu egingo zaizu. - proxy-remote-dns = .label = Bideratu DNSa proxy bidez SOCKS v5 erabiltzean .accesskey = d - proxy-enable-doh = .label = Gaitu HTTPS gaineko DNSa .accesskey = b diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/dock-options.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/dock-options.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/dock-options.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/dock-options.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -21,3 +21,4 @@ .label = Mezu berrien kopurua .accesskey = k notification-settings-info = Jakinarazpen paneleko etiketa ezgaitu dezakezu sistemaren hobespenetan. +notification-settings-info2 = Jakinarazpen paneleko etiketa ezgaitu dezakezu sistemaren ezarpenetan. diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/preferences.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,111 +4,72 @@ close-button = .aria-label = Itxi - preferences-doc-title = Hobespenak - +preferences-doc-title2 = Ezarpenak category-list = .aria-label = Kategoriak - pane-general-title = Orokorra category-general = .tooltiptext = { pane-general-title } - pane-compose-title = Mezu-prestatzea category-compose = .tooltiptext = Mezu-prestatzea - pane-privacy-title = Pribatutasuna eta segurtasuna category-privacy = .tooltiptext = Pribatutasuna eta segurtasuna - pane-chat-title = Txata category-chat = .tooltiptext = Txata - pane-calendar-title = Calendar category-calendar = .tooltiptext = Calendar - general-language-and-appearance-header = Hizkuntza eta itxura - general-incoming-mail-header = Sarrerako postak - general-files-and-attachment-header = Fitxategi eta eranskinak - general-tags-header = Etiketak - general-reading-and-display-header = Irakurtze eta bistaratzea - general-updates-header = Eguneraketak - general-network-and-diskspace-header = Sarea eta diskoko lekua - general-indexing-label = Indexatzen - composition-category-header = Mezu-prestatzea - composition-attachments-header = Eranskinak - composition-spelling-title = Ortografia - compose-html-style-title = HTML estiloa - composition-addressing-header = Helbideratzea - privacy-main-header = Pribatutasuna - privacy-passwords-header = Pasahitzak - privacy-junk-header = Zaborra - collection-header = { -brand-short-name } datuen bilketa eta erabilera - collection-description = Aukerak ematen ahalegintzen gara { -brand-short-name } denontzat hobetzeko behar ditugun datuak soilik biltzeko. Informazio pertsonala jaso aurretik zure baimena eskatzen dugu beti. collection-privacy-notice = Pribatutasun-oharra - collection-health-report-telemetry-disabled = Jada ez duzu baimentzen { -vendor-short-name }(e)k datu tekniko eta interakziozkoak kapturatzea. Iraganeko datu guztiak 30 egunen buruan ezabatuko dira. collection-health-report-telemetry-disabled-link = Argibide gehiago - collection-health-report = .label = Baimendu { -brand-short-name }(r)i datu tekniko eta interakziozkoak { -vendor-short-name }ra bidaltzea .accesskey = B collection-health-report-link = Argibide gehiago - # This message is displayed above disabled data sharing options in developer builds # or builds with no Telemetry support available. collection-health-report-disabled = Datuen berri ematea desgaituta dago eraikitze-konfigurazio honetarako - collection-backlogged-crash-reports = .label = Baimendu { -brand-short-name }(r)i atzeratutako hutsegite-txostenak zuregatik bidaltzea .accesskey = B collection-backlogged-crash-reports-link = Argibide gehiago - privacy-security-header = Segurtasuna - privacy-scam-detection-title = Iruzur detekzioa - privacy-anti-virus-title = Antibirusa - privacy-certificates-title = Ziurtagiriak - chat-pane-header = Txata - chat-status-title = Egoera - chat-notifications-title = Jakinarazpenak - chat-pane-styling-header = Diseinua - choose-messenger-language-description = Aukeratu { -brand-short-name }(e)k menuak, mezuak eta jakinarazpenak erakusteko erabiliko dituen hizkuntzak. manage-messenger-languages-button = .label = Ezarri ordezkoak .accesskey = i confirm-messenger-language-change-description = Barrabiarazi { -brand-short-name } aldaketa hauek aplikatzeko confirm-messenger-language-change-button = Aplikatu eta berrabiarazi - update-setting-write-failure-title = Errorea eguneratze hobespenak gordetzean - # Variables: # $path (String) - Path to the configuration file # The newlines between the main text and the line containing the path is @@ -117,16 +78,12 @@ { -brand-short-name }(e)k errore bat aurkitu du eta ez du aldaketa hau gorde. Kontuan izan eguneraketen hobespen hau ezartzeak azpiko fitxategia idazteko baimenak behar dituela. Zu edo sistema-kudeatzaile bat errorea konpontzeko moduan izan zaitezkete erabiltzaileen taldeari fitxategi honetarako kontrol osoa emanez. Ezin da fitxategira idatzi: { $path } - update-in-progress-title = Eguneratzea egiten - update-in-progress-message = { -brand-short-name } eguneratze honekin jarraitzea nahi duzu? - update-in-progress-ok-button = &Baztertu # Continue is the cancel button so pressing escape or using a platform standard # method of closing the UI will not discard the update. update-in-progress-cancel-button = &Jarraitu - account-button = Kontu-ezarpenak open-addons-sidebar-button = Gehigarriak eta itxurak @@ -134,13 +91,11 @@ # This message can be seen by trying to add a Primary Password. primary-password-os-auth-dialog-message-win = Pasahitz nagusi bat sortzeko, sartu zure Windows kredentzialak. Honek zure kontuen segurtasuna babesten laguntzen du. - # This message can be seen by trying to add a Primary Password. # The macOS strings are preceded by the operating system with "Thunderbird is trying to " # and includes subtitle of "Enter password for the user "xxx" to allow this." These # notes are only valid for English. Please test in your locale. primary-password-os-auth-dialog-message-macosx = Sortu pasahitz nagusia - # Don't change this label. master-password-os-auth-dialog-caption = { -brand-full-name } @@ -150,32 +105,28 @@ .key = f focus-search-shortcut-alt = .key = k - general-legend = { -brand-short-name } hasiera-orria - start-page-label = .label = { -brand-short-name } abiaraztean, erakutsi hasiera-orria mezuaren eremuan .accesskey = b - location-label = .value = Kokalekua: .accesskey = o restore-default-label = .label = Berrezarri lehenetsia .accesskey = r - default-search-engine = Bilatzaile lehenetsia -add-search-engine = - .label = Gehitu fitxategitik - .accesskey = f +add-web-search-engine = + .label = Gehitu… + .accesskey = G remove-search-engine = .label = Kendu .accesskey = K - +add-opensearch-provider-title = Gehitu OpenSearch hornitzailea +adding-opensearch-provider-failed-title = OpenSearch hornitzailea gehitzean huts egin du minimize-to-tray-label = .label = { -brand-short-name } txikitzen denean, mugitu erretilura .accesskey = t - new-message-arrival = Mezu berri bat iristerakoan: mail-play-sound-label = .label = @@ -191,30 +142,23 @@ mail-play-button = .label = Erreproduzitu .accesskey = p - change-dock-icon = Aldatu aplikazio-ikonoaren hobespenak app-icon-options = .label = Aplikazio-ikonoaren aukerak… .accesskey = n - notification-settings = Alertak eta soinu lehenetsiak desgaitu dezakezu jakinarazpen paneleko sistemaren hobespenetan. - animated-alert-label = .label = Erakutsi abisua .accesskey = s customize-alert-label = .label = Pertsonalizatu… .accesskey = P - biff-use-system-alert = .label = Erabili sistema jakinarazpenak - tray-icon-unread-label = .label = Erakutsi erretiluko ikonoa mezu irakurri gabeentzat .accesskey = E - tray-icon-unread-description = Gomendagarria zeregin-barra botoi txikiak erabiltzean - mail-system-sound-label = .label = Lehenetsitako sistema-soinua posta berriarentzat .accesskey = s @@ -224,27 +168,21 @@ mail-browse-sound-button = .label = Arakatu… .accesskey = A - enable-gloda-search-label = .label = Gaitu bilaketa orokorra eta indexatzailea .accesskey = i - datetime-formatting-legend = Data eta denboraren formatua language-selector-legend = Hizkuntza - allow-hw-accel = .label = Erabili hardware azelerazioa erabilgarri dagoenean .accesskey = h - store-type-label = .value = Mezuen biltegiratze mota kontu berrientzako: .accesskey = m - mbox-store-label = .label = Karpeta bakoitzeko fitxategi bat (mbox) maildir-store-label = .label = Fitxategia mezuko (maildir) - scrolling-legend = Korritzea autoscroll-label = .label = Erabili korritze automatikoa @@ -252,7 +190,6 @@ smooth-scrolling-label = .label = Erabili korritze leuna .accesskey = u - system-integration-legend = Sistemaren integrazioa always-check-default = .label = Egiaztatu beti { -brand-short-name } posta-bezero lehenetsia dela abiaraztean @@ -260,7 +197,6 @@ check-default-button = .label = Egiaztatu orain… .accesskey = o - # Note: This is the search engine name for all the different platforms. # Platforms that don't support it should be left blank. search-engine-name = @@ -269,26 +205,20 @@ [windows] Windows bilaketa *[other] { "" } } - search-integration-label = .label = Baimendu { search-engine-name }(r)i mezuak bilatzea .accesskey = B - config-editor-button = .label = Konfigurazio-editorea… .accesskey = g - return-receipts-description = Zehaztu hartu-agiriak nola kudeatzen dituen { -brand-short-name }(e)k return-receipts-button = .label = Hartu-agiriak… .accesskey = r - update-app-legend = { -brand-short-name } eguneraketak - # Variables: # $version (String): version of Thunderbird, e.g. 68.0.1 update-app-version = Bertsioa { $version } - allow-description = Baimendu { -brand-short-name }(r)i automatic-updates-label = .label = Instalatu eguneraketak automatikoki (gomendatua: hobetutako segurtasuna) @@ -296,40 +226,30 @@ check-updates-label = .label = Egiaztatu eguneraketarik dagoen baina galdetu instalatu nahi ditudan .accesskey = E - update-history-button = .label = Erakutsi eguneraketen historia .accesskey = n - use-service = .label = Erabili atzeko planoko zerbitzua eguneraketak instalatzeko .accesskey = z - cross-user-udpate-warning = Ezarpenak leiho guztiei aplikatuko zaizkie eta { -brand-short-name } profil guztiei, { -brand-short-name } instalazio hau erabiliz. - networking-legend = Konexioa proxy-config-description = Konfiguratu { -brand-short-name } Internetera nola konektatzen den - network-settings-button = .label = Ezarpenak… .accesskey = n - offline-legend = Lineaz kanpo offline-settings = Konfiguratu lineaz kanpoko ezarpenak - offline-settings-button = .label = Lineaz kanpo… .accesskey = o - diskspace-legend = Diskoko lekua offline-compact-folder = .label = Trinkotu karpeta guztiak hau baino gehiago aurrezten denean: .accesskey = k - offline-compact-folder-automatically = .label = Galdetu beti trinkotu aurretik .accesskey = t - compact-folder-size = .value = MB guztira @@ -340,7 +260,6 @@ use-cache-before = .value = Erabili gehienez .accesskey = E - use-cache-after = MB cachearentzat ## @@ -348,42 +267,31 @@ smart-cache-label = .label = Gainidatzi automatikoki cachearen kudeaketa .accesskey = a - clear-cache-button = .label = Garbitu orain .accesskey = G - fonts-legend = Letra-tipoak eta koloreak - default-font-label = .value = Letra-tipo lehenetsia: .accesskey = L - default-size-label = .value = Tamaina: .accesskey = T - font-options-button = .label = Letra-tipoak… .accesskey = L - color-options-button = .label = Koloreak… .accesskey = K - display-width-legend = Testu-arrunteko mezuak - # Note : convert-emoticons-label 'Emoticons' are also known as 'Smileys', e.g. :-) convert-emoticons-label = .label = Bistaratu aurpegierak eta grafikoak .accesskey = a - display-text-label = Zitatutako testu-arrunteko mezuak bistaratzean: - style-label = .value = Estiloa: .accesskey = i - regular-style-item = .label = Arrunta bold-style-item = @@ -392,37 +300,25 @@ .label = Etzana bold-italic-style-item = .label = Lodi etzana - size-label = .value = Tamaina: .accesskey = T - regular-size-item = .label = Arrunta bigger-size-item = .label = Handiagoa smaller-size-item = .label = Txikiagoa - quoted-text-color = .label = Kolorea: .accesskey = o - search-handler-table = .placeholder = Iragazi eduki mota eta ekintzak - -type-column-label = - .label = Eduki mota - .accesskey = t - -action-column-label = - .label = Ekintza - .accesskey = a - +type-column-header = Eduki mota +action-column-header = Ekintza save-to-label = .label = Gorde fitxategiak hemen: .accesskey = G - choose-folder-label = .label = { PLATFORM() -> @@ -434,30 +330,22 @@ [macos] A *[other] A } - always-ask-label = .label = Beti galdetu niri fitxategiak non gorde .accesskey = B - - display-tags-text = Mezuak sailkatu eta lehentasunak zehazteko erabil daitezke etiketak. - new-tag-button = .label = Berria… .accesskey = B - edit-tag-button = .label = Editatu… .accesskey = E - delete-tag-button = .label = Ezabatu .accesskey = z - auto-mark-as-read = .label = Markatu automatikoki mezuak irakurrita gisa .accesskey = a - mark-read-no-delay = .label = Bistaratu bezain laster .accesskey = B @@ -468,33 +356,26 @@ mark-read-delay = .label = Denbora batez bistaratu eta gero: .accesskey = e - seconds-label = segundoz ## open-msg-label = .value = Ireki mezuak: - open-msg-tab = .label = Fitxa berrian .accesskey = t - open-msg-window = .label = Mezu-leiho berrian .accesskey = h - open-msg-ex-window = .label = Dagoen mezu-leihoan .accesskey = D - close-move-delete = .label = Itxi mezu-leihoa/fitxa lekuz aldatzean edo ezabatzean .accesskey = I - display-name-label = .value = Bistaratzeko izena: - condensed-addresses-label = .label = Erakutsi nire helbide-liburuko pertsonen bistarazte-izena bakarrik .accesskey = p @@ -504,13 +385,10 @@ forward-label = .value = Birbidali mezuak: .accesskey = B - inline-label = .label = Barnean - as-attachment-label = .label = Eranskin gisa - extension-label = .label = gehitu luzapena fitxategi-izenari .accesskey = f @@ -521,7 +399,6 @@ auto-save-label = .label = Gorde automatikoki .accesskey = u - auto-save-end = minutuan behin ## @@ -529,250 +406,182 @@ warn-on-send-accel-key = .label = Eskatu berrespena mezua bidaltzeko laster-tekla erabiltzean .accesskey = i - spellcheck-label = .label = Egiaztatu ortografia bidali aurretik .accesskey = g - spellcheck-inline-label = .label = Gaitu ortografia egiaztatzea idatzi ahala .accesskey = r - language-popup-label = .value = Hizkuntza: .accesskey = z - download-dictionaries-link = Deskargatu hiztegi gehiago - font-label = .value = Letra-tipoa: .accesskey = r - font-size-label = .value = Tamaina: .accesskey = t - default-colors-label = .label = Erabili irakurlearen kolore lehenetsiak .accesskey = l - font-color-label = .value = Testuaren kolorea: .accesskey = s - bg-color-label = .value = Atzeko planoko kolorea: .accesskey = A - restore-html-label = .label = Berrezarri lehenetsiak .accesskey = r - default-format-label = .label = Erabili paragrafo formatua testu gorputzaren ordez lehenetsirik .accesskey = p - format-description = Konfiguratu testuaren formatuaren portaera - send-options-label = .label = Bidalketa-aukerak… .accesskey = B - autocomplete-description = Bilatu bat datozen sarrerak mezuak helbideratzean: - ab-label = .label = Helbide-liburu lokaletan .accesskey = a - directories-label = .label = Direktorio-zerbitzarian: .accesskey = D - directories-none-label = .none = Bat ere ez - edit-directories-label = .label = Editatu direktorioak… .accesskey = E - email-picker-label = .label = Gehitu hemen automatikoki bidalitako posta-helbideak: .accesskey = t - default-directory-label = .value = Helbide liburu leihoko abioko direktorio lehenetsia: .accesskey = H - default-last-label = .none = Azken direktorio erabilia - attachment-label = .label = Egiaztatu eranskinak falta diren .accesskey = f - attachment-options-label = .label = Gako-hitzak… .accesskey = k - enable-cloud-share = .label = Eskaini partekatzea hau baino handiagoak diren fitxategientzat: cloud-share-size = .value = MB - add-cloud-account = .label = Gehitu… .accesskey = G .defaultlabel = Gehitu… - remove-cloud-account = .label = Kendu .accesskey = K - find-cloud-providers = .value = Bilatu hornitzaile gehiago… - cloud-account-description = Gehitu Filelink biltegiratze-zerbitzu berri bat - ## Privacy Tab mail-content = Postaren edukia - remote-content-label = .label = Baimendu urruneko edukia mezuetan .accesskey = B - exceptions-button = .label = Salbuespenak… .accesskey = e - remote-content-info = .value = Urruneko edukiaren pribatutasun-arazoei buruzko argibide gehiago - web-content = Web edukia - history-label = .label = Gogoratu bisitatu ditudan webgune eta loturak .accesskey = G - cookies-label = .label = Onartu guneetako cookieak .accesskey = O - third-party-label = .value = Onartu hirugarrenen cookieak: .accesskey = n - third-party-always = .label = Beti third-party-never = .label = Inoiz ez third-party-visited = .label = Bisitatutakoetatik - keep-label = .value = Mantendu: .accesskey = M - keep-expire = .label = iraungi arte keep-close = .label = { -brand-short-name } itxi arte keep-ask = .label = galdetu niri beti - cookies-button = .label = Erakutsi cookieak… .accesskey = E - do-not-track-label = .label = Bidali webguneei "Do Not Track" seinalea zure jarraipena ez egitea adierazteko .accesskey = n - learn-button = .label = Argibide gehiago - passwords-description = { -brand-short-name }(e)k pasahitzen informazioa gogora dezake zure kontu guztientzat. - passwords-button = .label = Gordetako pasahitzak… .accesskey = G - - primary-password-description = Pasahitz nagusiak zure pasahitz guztiak babesten ditu, baina saio bakoitzeko behin sartu behar duzu. - primary-password-label = .label = Erabili pasahitz nagusia .accesskey = E - primary-password-button = .label = Aldatu pasahitz nagusia… .accesskey = A - forms-primary-pw-fips-title = Une honetan FIPS moduan zaude. FIPS moduak pasahitz nagusia ezartzea eskatzen du. forms-master-pw-fips-desc = Pasahitz aldaketak huts egin du - - junk-description = Ezarri zabor-postaren ezarpen lehenetsiak. Kontu bakoitzari lotutako zabor-postaren ezarpenak kontu-ezarpenetan konfiguratu daitezke. - junk-label = .label = Mezuak zabor gisa markatzen ditudanean: .accesskey = z - junk-move-label = .label = Aldatu lekuz kontuaren "Zaborra" karpetara .accesskey = d - junk-delete-label = .label = Ezabatu .accesskey = E - junk-read-label = .label = Markatu zabor-mezuak irakurrita gisa .accesskey = M - junk-log-label = .label = Gaitu zabor-iragazki moldakorraren loga .accesskey = G - junk-log-button = .label = Erakutsi loga .accesskey = s - reset-junk-button = .label = Berrezarri trebatze-datuak .accesskey = r - phishing-description = { -brand-short-name }(e)k mezuak azter ditzake posta-iruzurrak bilatzeko, iruzur egiteko erabil daitezkeen oinarrizko teknikak begiratuz. - phishing-label = .label = Esaidazu irakurtzen ari naizen mezua posta-iruzurra izan daitekeen .accesskey = E - antivirus-description = { -brand-short-name } erraztuko du antibirus softwareak datozen mezuak aztertu ditzan lokalki gorde aurretik. - antivirus-label = .label = Baimendu antibirus bezeroari mezuak koarentenan jartzea .accesskey = k - certificate-description = Webgune batek nire ziurtagiri pertsonala eskatzen duenean: - certificate-auto = .label = Hautatu bat automatikoki .accesskey = S - certificate-ask = .label = Galdetu beti .accesskey = G - ocsp-label = .label = Galdetu OCSP erantzule-zerbitzariei ziurtagiriak baliozkoak diren egiaztatzeko .accesskey = G - certificate-button = .label = Kudeatu ziurtagiriak… .accesskey = K - security-devices-button = .label = Segurtasun-gailuak… .accesskey = S @@ -782,10 +591,8 @@ startup-label = .value = { -brand-short-name } abiatzean: .accesskey = a - offline-label = .label = Mantendu txat-kontuak deskonektatuta - auto-connect-label = .label = Konektatu txat-kontuak automatikoki @@ -798,7 +605,6 @@ idle-label = .label = Jakinarazi nire kontaktuei inaktibo nagoela .accesskey = i - idle-time-label = minutu ondoren ## @@ -806,24 +612,19 @@ away-message-label = .label = eta ezarri nire egoera Kanpoan egoera-mezu honekin: .accesskey = K - send-typing-label = .label = Bidali idazketa-jakinarazpenak berriketetan .accesskey = d - notification-label = Zuri zuzendutako mezuak iristean: - show-notification-label = .label = Erakutsi jakinarazpena: .accesskey = n - notification-all = .label = bidaltzailearen izenarekin eta mezuaren aurrebistarekin notification-name = .label = bidaltzailearen izenarekin soilik notification-empty = .label = inolako informaziorik gabe - notification-type-label = .label = { PLATFORM() -> @@ -835,31 +636,24 @@ [macos] A *[other] K } - chat-play-sound-label = .label = Erreproduzitu soinua .accesskey = d - chat-play-button = .label = Erreproduzitu .accesskey = p - chat-system-sound-label = .label = Lehenetsitako sistema-soinua posta berriarentzat .accesskey = i - chat-custom-sound-label = .label = Erabili hurrengo soinu-fitxategia .accesskey = u - chat-browse-sound-button = .label = Arakatu… .accesskey = A - theme-label = .value = Gaia: .accesskey = G - style-thunderbird = .label = Thunderbird style-bubbles = @@ -870,15 +664,12 @@ .label = Papera orriak style-simple = .label = Sinplea - preview-label = Aurrebista: no-preview-label = Aurrebista ez dago erabilgarri no-preview-description = Gai hau ez da baliokoa edo une honetan ez dago erabilgarri (desgaitu gehigarria, modu-segurua, …). - chat-variant-label = .value = Aldaerak: .accesskey = A - # This is used to determine the width of the search field in about:preferences, # in order to make the entire placeholder string visible # @@ -893,13 +684,25 @@ ## Preferences UI Search Results -search-results-header = Bilaketaren emaitzak +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input2 = + .style = width: 15.4em + .placeholder = Bilatu ezarpenetan +## Settings UI Search Results + +search-results-header = Bilaketaren emaitzak # `` will be replaced by the search term. search-results-empty-message = { PLATFORM() -> [windows] Barkatu! Aukeretan ez dago "" bilaketarako emaitzarik. *[other] Barkatu! Hobespenetan ez dago "" bilaketarako emaitzarik. } - search-results-help-link = Laguntza behar duzu? Bisitatu { -brand-short-name }(r)en laguntza diff -Nru thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/receipts.ftl thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/receipts.ftl --- thunderbird-91.7.0+build2/l10n/eu/mail/messenger/preferences/receipts.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/mail/messenger/preferences/receipts.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -4,48 +4,35 @@ receipts-dialog-window = .title = Hartu-agiriak - -return-receipt-checkbox = +return-receipt-checkbox-control = .label = Eskatu beti hartu-agiria mezuak bidaltzean - .acceskey = h - + .accesskey = E receipt-arrive-label = Hartu-agiri bat iristean: - -receipt-leave-radio = +receipt-leave-radio-control = .label = Utzi nire sarrera-ontzian - .acceskey = s - -receipt-move-radio = + .accesskey = s +receipt-move-radio-control = .label = Aldatu lekuz "Bidalitakoak" karpetara - .acceskey = A - + .accesskey = l receipt-request-label = Hartu-agiri baten eskaera jasotzen dudanean: - -receipt-return-never-radio = - .label = Ez bidali inoiz hartu-agiririk - .acceskey = n - -receipt-return-some-radio = +receipt-return-never-radio-control = + .label = Ez bidali inoiz hartu-agiria + .accesskey = h +receipt-return-some-radio-control = .label = Baimendu hartu-agiriak mezu batzuentzat - .acceskey = r - -receipt-not-to-cc = + .accesskey = m +receipt-not-to-cc-label = .value = Ez banago mezuaren Nori edo Cc eremuetan: - .acceskey = N - + .accesskey = e receipt-send-never-label = .label = Inoiz ez bidali - receipt-send-always-label = .label = Bidali beti - receipt-send-ask-label = .label = Galdetu niri - -sender-outside-domain = +sender-outside-domain-label = .value = Bidaltzailea nire domeinutik kanpo badago: - .acceskey = B - -other-cases-label = + .accesskey = k +other-cases-text-label = .value = Beste kasu guztietan: - .acceskey = B + .accesskey = b diff -Nru thunderbird-91.7.0+build2/l10n/eu/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/eu/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/eu/netwerk/necko.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/netwerk/necko.properties 2022-04-15 07:52:36.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired="%1$S" cookiea baztertu egin da dagoeneko iraungita dagoelako. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness="%1$S" cookiea baztertu egin da guneen arteko testuinguruan izan eta bere "SameSite" balioa "Lax" edo "Strict" delako. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Abisua: zaharkituta dago '%1$S'; erabili '%2$S' horren ordez diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/eu/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/eu/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:52:36.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Itxi irakurtzeko ikuspegia @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Kolore-eskema argia aboutReader.toolbar.colorschemedark = Kolore-eskema iluna aboutReader.toolbar.colorschemesepia = Kolore-eskema sepia +aboutReader.toolbar.colorschemeauto = Kolore-eskema automatikoa diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/eu/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/eu/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/chrome/global/narrate.properties 2022-04-15 07:52:36.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Entzun back = Atzera start = Hasi stop = Gelditu +# %S is the keyboard shortcut for the start command +start-label = Hasi (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Gelditu (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Aurrera speed = Abiadura selectvoicelabel = Ahotsa: diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/chrome/mozapps/extensions/extensions.properties thunderbird-91.8.1+build1/l10n/eu/toolkit/chrome/mozapps/extensions/extensions.properties --- thunderbird-91.7.0+build2/l10n/eu/toolkit/chrome/mozapps/extensions/extensions.properties 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/chrome/mozapps/extensions/extensions.properties 2022-04-15 07:52:36.000000000 +0000 @@ -68,6 +68,7 @@ type.plugin.name=Pluginak type.dictionary.name=Hiztegiak type.service.name=Zerbitzuak +type.sitepermission.name=Gunearen baimenak type.legacy.name=Legatu-hedapenak type.unsupported.name=Ez dago onartuta @@ -80,5 +81,7 @@ listHeading.locale=Kudeatu zure hizkuntzak listHeading.dictionary=Kudeatu zure hiztegiak +listHeading.sitepermission=Kudeatu zure gunearen baimenak + searchLabel.extension=Bilatu hedapen gehiago searchLabel.theme=Bilatu itxura gehiago diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/about/aboutAddons.ftl thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/about/aboutAddons.ftl --- thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/about/aboutAddons.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/about/aboutAddons.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -132,6 +132,9 @@ addon-category-recent-updates = Azken eguneraketak addon-category-recent-updates-title = .title = Azken eguneraketak +addon-category-sitepermission = Gunearen baimenak +addon-category-sitepermission-title = + .title = Gunearen baimenak ## These are global warnings @@ -280,6 +283,8 @@ dictionary-disabled-heading = Desgaituta locale-enabled-heading = Gaituta locale-disabled-heading = Desgaituta +sitepermission-enabled-heading = Gaituta +sitepermission-disabled-heading = Desgaituta always-activate-button = Aktibatu beti never-activate-button = Ez aktibatu inoiz addon-detail-author-label = Egilea @@ -356,6 +361,7 @@ addon-permissions-learnmore = Baimenei buruzko argibide gehiago recommended-extensions-heading = Gomendatutako hedapenak recommended-themes-heading = Gomendatutako itxurak +addon-sitepermissions-required = Ondorengo gaitasunak baimentzen dizkio { $hostname } guneari: # A recommendation for the Firefox Color theme shown at the bottom of the theme # list view. The "Firefox Color" name itself should not be translated. recommended-theme-1 = Sortzaile izan nahi? Egizu zure itxura propioa Firefox Color erabiliz. @@ -368,6 +374,7 @@ dictionary-heading = Kudeatu zure hiztegiak locale-heading = Kudeatu zure hizkuntzak updates-heading = Kudeatu zure eguneraketak +sitepermission-heading = Kudeatu zure gunearen baimenak discover-heading = Pertsonalizatu zure { -brand-short-name } shortcuts-heading = Kudeatu hedapenen lasterbideak default-heading-search-label = Bilatu gehigarri gehiago diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -18,6 +18,8 @@ about-webrtc-aec-logging-off-state-label = Hasi AEC erregistroa about-webrtc-aec-logging-on-state-label = Gelditu AEC erregistroa about-webrtc-aec-logging-on-state-msg = AEC erregistroa aktibo (hitz egin denbora batez deitu duenarekin eta gelditu kaptura gero) +# The autorefresh checkbox causes the page to autorefresh its content when checked +about-webrtc-auto-refresh-label = Automatikoki berritu ## @@ -183,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] Marko { $frames } + *[other] { $frames } marko + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] Kanal { $channels } + *[other] { $channels } kanal + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/about/abuseReports.ftl thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/about/abuseReports.ftl --- thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/about/abuseReports.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/about/abuseReports.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -2,26 +2,22 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Localized string used as the dialog window title (a new behavior locked -# behind the "extensions.abuseReport.openDialog" preference). +# Localized string used as the dialog window title. # "Report" is a noun in this case, "Report for AddonName". # # Variables: # $addon-name (string) - Name of the add-on being reported abuse-report-dialog-title = { $addon-name } gehigarrirako txostena - abuse-report-title-extension = Salatu hedapen hau { -vendor-short-name }(r)i +abuse-report-title-sitepermission = Salatu guneei baimenak ematen dizkion hedapen hau { -vendor-short-name }(r)i abuse-report-title-theme = Salatu itxura hau { -vendor-short-name }(r)i abuse-report-subtitle = Zein da arazoa? - # Variables: # $author-name (string) - Name of the add-on author abuse-report-addon-authored-by = egilea: { $author-name } - abuse-report-learnmore = Ez zaude ziur zein arazo hautatu? Hedapen eta itxurak salatzeko argibide gehiago - abuse-report-submit-description = Azaldu arazoa (aukerakoa) abuse-report-textarea = .placeholder = Guretzat errazagoa da arazoari irtenbidea ematea datu zehatzak baditugu. Azaldu mesedez zein den izan duzun arazoa. Eskerrik asko weba osasuntsu mantentzen laguntzeagatik. @@ -35,12 +31,6 @@ abuse-report-submit-button = Bidali ## Message bars descriptions. - - -## Variables: -## $addon-name (string) - Name of the add-on - -## Message bars descriptions. ## ## Variables: ## $addon-name (string) - Name of the add-on @@ -50,6 +40,7 @@ abuse-report-messagebar-submitted = Eskerrik asko salaketa bidaltzeagatik. { $addon-name } gehigarria kendu egin nahi duzu? abuse-report-messagebar-submitted-noremove = Eskerrik asko salaketa bidaltzeagatik. abuse-report-messagebar-removed-extension = Eskerrik asko salaketa bidaltzeagatik. { $addon-name } hedapena kendu egin duzu. +abuse-report-messagebar-removed-sitepermission = Eskerrik asko salaketa bidaltzeagatik. Guneei baimenak ematen dizkion { $addon-name } hedapena kendu egin duzu. abuse-report-messagebar-removed-theme = Eskerrik asko salaketa bidaltzeagatik. { $addon-name } itxura kendu egin duzu. abuse-report-messagebar-error = Errorea gertatu da { $addon-name } gehigarrirako salaketa bidaltzerakoan. abuse-report-messagebar-error-recent-submit = { $addon-name } gehigarrirako salaketa ez da bidali orain dela gutxi beste salaketa bat bidali delako. @@ -58,6 +49,8 @@ abuse-report-messagebar-action-remove-extension = Bai, kendu abuse-report-messagebar-action-keep-extension = Ez, mantendu +abuse-report-messagebar-action-remove-sitepermission = Bai, kendu +abuse-report-messagebar-action-keep-sitepermission = Ez, mantendu abuse-report-messagebar-action-remove-theme = Bai, kendu abuse-report-messagebar-action-keep-theme = Ez, mantendu abuse-report-messagebar-action-retry = Saiatu berriro @@ -67,29 +60,23 @@ abuse-report-damage-reason-v2 = Nire ordenagailua kaltetu du edo nire datuak arriskuan jarri ditu abuse-report-damage-example = Adibidea: malwarea txertatu du edo datuak lapurtu ditu - abuse-report-spam-reason-v2 = Spama du edo nahi ez ditudan iragarkiak ditu abuse-report-spam-example = Adibidea: iragarkiak txertatzen ditu webguneetan - abuse-report-settings-reason-v2 = Nire bilaketa-motorra, hasiera-orria edo fitxa berria aldatu ditu galdetu gabe eta onespenik gabe abuse-report-settings-suggestions = Hedapena salatu aurretik, zure ezarpenak aldatzen saia zaitezke: abuse-report-settings-suggestions-search = Aldatu zure bilaketa-ezarpen lehenetsiak abuse-report-settings-suggestions-homepage = Aldatu zure hasiera-orria eta fitxa berria - abuse-report-deceptive-reason-v2 = Benetan ez den zerbait izaten saiatu da abuse-report-deceptive-example = Adibidea: gezurretako azalpen edo iruditeria - abuse-report-broken-reason-extension-v2 = Ez dabil, webguneak apurtzen ditu edo { -brand-product-name } moteltzen du +abuse-report-broken-reason-sitepermission-v2 = Ez dabil, webguneak apurtzen ditu edo { -brand-product-name } moteltzen du abuse-report-broken-reason-theme-v2 = Ez dabil edo nabigatzailearen bistaratzea apurtzen du abuse-report-broken-example = Adibidea: eginbideak makalak edo erabiltzeko zailak dira, edo ez dabil; webguneetako zatiak ez dabiltza edo ezohikoak dirudite abuse-report-broken-suggestions-extension = Badirudi programa-errore bat aurkitu duzula. Hemen bertan horren berri emateaz gain, arazoa konpontzeko biderik onena zuzenean hedapenaren garatzailearekin harremanetan jartzea da. Garatzaileari buruzko informazioa eskuratzeko, bisitatu hedapenaren webgunea. +abuse-report-broken-suggestions-sitepermission = Badirudi programa-errore bat aurkitu duzula. Hemen bertan horren berri emateaz gain, arazoa konpontzeko biderik onena zuzenean webgunearen garatzailearekin harremanetan jartzea da. Garatzaileari buruzko informazioa eskuratzeko, bisitatu webgunea. abuse-report-broken-suggestions-theme = Badirudi programa-errore bat aurkitu duzula. Hemen bertan horren berri emateaz gain, arazoa konpontzeko biderik onena zuzenean itxuraren garatzailearekin harremanetan jartzea da. Garatzaileari buruzko informazioa eskuratzeko, bisitatu itxuraren webgunea. - abuse-report-policy-reason-v2 = Eduki gaitzesgarria, indarkeriazkoa edo ilegala du abuse-report-policy-suggestions = Oharra: Copyright eta marka erregistratuei buruzko arazoak aparteko prozesu batean salatu behar dira. Arazoaren berri emateko, erabili jarraibide hauek. - abuse-report-unwanted-reason-v2 = Inoiz ez dut nahi izan eta ez dakit nola gainetik kendu abuse-report-unwanted-example = Adibidea: aplikazio batek nire baimenik gabe instalatu du - abuse-report-other-reason = Beste zerbait - diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -9,11 +9,6 @@ experimental-features-css-masonry-description = CSS Masonry Layout eginbide esperimentalaren euskarria gaitzen du. Ikusi azalpena eginbidearen goi mailako deskribapen baterako. Iritzia emateko, idatzi iruzkina GitHub issue honetan edo bug honetan. # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. -experimental-features-css-cascade-layers = - .label = CSS: teilakatutako geruzak -experimental-features-css-cascade-layers-description = CSS teilakatutako geruzen euskarria gaitzen du. Xehetasunetarako ikusi lantze-fasean dagoen espezifikazioa<. Eginbide honekin lotutako akatsetarako, osatu bug berriak 1699215 buga blokeatuz. -# The title of the experiment should be kept in English as it may be referenced -# by various online articles and is technical in nature. experimental-features-web-gpu2 = .label = Web API: WebGPU experimental-features-web-gpu-description2 = API berri honek behe mailako euskarria ematen du konputazioak eta grafikoen errendatzea burutzeko erabiltzailearen gailu edo ordenagailuko GPUa erabiliz. Espezifikazioa oraindik lantze-fasean dago. Ikusi 1602129 buga xehetasun gehiagorako. @@ -94,3 +89,7 @@ experimental-features-ime-search = .label = Helbide-barra: erakutsi emaitzak IME konposizioan experimental-features-ime-search-description = Sinbolo konplexuak (Asia Ekialdeko edo Indiako hizkuntza idatzietakoak, adibidez) teklatu bidez idaztea baimentzen duen tresna da IME bat (Input Method Editor). Esperimentu hau gaitzean helbide-barra irekita mantenduko da, bilaketa-emaitzak eta iradokizunak erakutsiz IME erabili ahala testua idazteko. Konturatu IMEak helbide-barrako emaitzen gainetik bistara dezakeela panel bat, hortaz hobespen hau gomendatzen da soilik IMEak mota honetako panela erabiltzen ez duenean. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name } 100 User-Agent katea +experimental-features-firefox-100-description = Konfiguratu { -brand-short-name } webguneetara 100. { -brand-product-name } bertsioaren itxurak egiten dituen User-Agent karaktere-katea bidaltzeko. Erabili ezarpen hau probatzeko webguneak ondo arituko diren { -brand-short-name } hiru digituko bertsio-zenbakira heltzen denean. Benetako { -brand-product-name } 100 bertsioa 2022ko maiatzean kaleratzea espero da, beraz hasi orain zure webguneak probatzen! diff -Nru thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/eu/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:37:45.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/eu/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:52:36.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socketa # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Isolatutako IPC aktorea ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/fi/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/fi/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/fi/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:52:44.000000000 +0000 @@ -0,0 +1,27 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } kutsui sinut: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Tallenna +calendar-invitation-panel-accept-button = Kyllä +calendar-invitation-panel-decline-button = Ei +calendar-invitation-panel-tentative-button = Ehkä +calendar-invitation-panel-reply-status = * Et ole vielä päättänyt tai vastannut +calendar-invitation-panel-prop-title-when = Aika: +calendar-invitation-panel-prop-title-location = Sijainti: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Osallistujat: +calendar-invitation-panel-prop-title-description = Kuvaus: diff -Nru thunderbird-91.7.0+build2/l10n/fi/calendar/calendar/calendar-itip-identity-dialog.ftl thunderbird-91.8.1+build1/l10n/fi/calendar/calendar/calendar-itip-identity-dialog.ftl --- thunderbird-91.7.0+build2/l10n/fi/calendar/calendar/calendar-itip-identity-dialog.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/calendar/calendar/calendar-itip-identity-dialog.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -5,3 +5,4 @@ calendar-itip-identity-dialog-title = Menossa juhliin kutsumatta? calendar-itip-identity-warning = Et ole vielä vierailijaluettelossa. calendar-itip-identity-label = Vastaa käyttäjänä: +calendar-itip-identity-label-none = Yhdistä tämä tapahtuma: diff -Nru thunderbird-91.7.0+build2/l10n/fi/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/fi/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/fi/devtools/client/aboutdebugging.ftl 2022-03-07 21:37:50.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/devtools/client/aboutdebugging.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Debugging - Setup - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Debugging - Runtime / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = This { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Setup - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB enabled - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB disabled - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Connected # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Disconnected - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = No devices discovered - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Connect - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Connecting… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Connection failed - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = Connection still pending, check for messages on the target browser - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = Connection timed out - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Waiting for browser… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Unplugged - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Debugging Support - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Help icon - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Refresh devices @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Setup - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Configure the connection method you wish to remotely debug your device with. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Use { about-debugging-this-firefox-runtime-name } to debug extensions and service workers on this version of { -brand-shorter-name }. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Connect a Device - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Enabling this will download and add the required Android USB debugging components to { -brand-shorter-name }. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = Enable USB Devices - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = Disable USB Devices - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Updating… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Enabled about-debugging-setup-usb-status-disabled = Disabled about-debugging-setup-usb-status-updating = Updating… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Enable Developer menu on your Android device. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Enable USB Debugging in the Android Developer Menu. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Enable USB Debugging in Firefox on the Android device. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Connect the Android device to your computer. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Problems connecting to the USB device? Troubleshoot - # Network section of the Setup page about-debugging-setup-network = .title = Network Location - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Problems connecting via network location? Troubleshoot - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Add - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = No network locations have been added yet. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Host - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Remove - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Invalid host “{ $host-value }”. The expected format is “hostname:portnumber”. - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Processes - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Profile performance - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Your browser configuration is not compatible with Service Workers. Learn more - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = The connected browser has an old version ({ $runtimeVersion }). The minimum supported version is ({ $minVersion }). This is an unsupported setup and may cause DevTools to fail. Please update the connected browser. Troubleshooting - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = This version of Firefox cannot debug Firefox for Android (68). We recommend installing Firefox for Android Nightly on your phone for testing. More details - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = The connected browser is more recent ({ $runtimeVersion }, buildID { $runtimeID }) than your { -brand-shorter-name } ({ $localVersion }, buildID { $localID }). This is an unsupported setup and may cause DevTools to fail. Please update Firefox. Troubleshooting - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Disconnect - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Enable connection prompt - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Disable connection prompt - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Profiler - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Nothing yet. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Inspect - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Load Temporary Add-on… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = There was an error during the temporary add-on installation. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Reload - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Remove - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Terminate background script # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Select manifest.json file or .xpi/.zip archive - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = This WebExtension has a temporary ID. Learn more - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = Manifest URL - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = Internal UUID - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Location - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = Extension ID - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Background script +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Running +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Stopped # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push .disabledTitle = Service Worker push is currently disabled for multiprocess { -brand-shorter-name } - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Start .disabledTitle = Service Worker start is currently disabled for multiprocess { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Unregister - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Listening for fetch events - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = Not listening for fetch events - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Running - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Stopped - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Registering - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Scope - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Push Service - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = Service Worker inspection is currently disabled for multiprocess { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Tab is not fully loaded and cannot be inspected - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Main Process - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Main Process for the target browser - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Multiprocess Toolbox - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Main Process and Content Processes for the target browser - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Close message - # Label text used for the error details of message component. about-debugging-message-details-label-error = Error details - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Warning details - # Label text used for default state of details of message component. about-debugging-message-details-label = Details diff -Nru thunderbird-91.7.0+build2/l10n/fi/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/fi/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/fi/devtools/client/compatibility.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/devtools/client/compatibility.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (experimental) compatibility-issue-prefixneeded = (prefix needed) compatibility-issue-deprecated-experimental = (deprecated, experimental) - compatibility-issue-deprecated-prefixneeded = (deprecated, prefix needed) compatibility-issue-experimental-prefixneeded = (experimental, prefix needed) compatibility-issue-deprecated-experimental-prefixneeded = (deprecated, experimental, prefix needed) @@ -43,7 +42,14 @@ [one] { $number } occurrence *[other] { $number } occurrences } - compatibility-no-issues-found = No compatibility issues found. compatibility-close-settings-button = .title = Close settings +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Compatibility issues in: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/fi/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/fi/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/fi/devtools/client/debugger.properties 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/devtools/client/debugger.properties 2022-04-15 07:52:43.000000000 +0000 @@ -642,6 +642,16 @@ ignoreContextItem.unignore=Unignore source ignoreContextItem.unignore.accesskey=U +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Ignore line +ignoreContextItem.ignoreLine.accesskey=l + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Unignore line +ignoreContextItem.unignoreLine.accesskey=n + # LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated # with the ignore lines context menu item ignoreContextItem.ignoreLines=Ignore lines diff -Nru thunderbird-91.7.0+build2/l10n/fi/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/fi/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/fi/devtools/client/netmonitor.properties 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/devtools/client/netmonitor.properties 2022-04-15 07:52:43.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=The string “%S” was removed from the beginning of the JSON shown below + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Query String: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL Parameters + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Request Headers: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Headers + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=name + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=value + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Body + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=payload + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Request Body: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Cancel +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Clear + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Remove item + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Back diff -Nru thunderbird-91.7.0+build2/l10n/fi/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/fi/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/fi/devtools/client/toolbox.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/devtools/client/toolbox.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Disable popup auto-hide +toolbox-meatball-menu-pseudo-locale-accented = Enable “accented” locale +toolbox-meatball-menu-pseudo-locale-bidi = Enable “bidi” locale ## diff -Nru thunderbird-91.7.0+build2/l10n/fi/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/fi/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/fi/devtools/client/toolbox-options.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/devtools/client/toolbox-options.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Enable remote debugging options-enable-remote-tooltip2 = .title = Turning this option on will allow to debug this browser instance remotely +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Enable custom formatters +options-enable-custom-formatters-tooltip = + .title = Turning this option on will allow sites to define custom formatters for DOM objects # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Enable Service Workers over HTTP (when toolbox is open) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/fi/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/fi/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/fi/devtools/client/webconsole.properties 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/devtools/client/webconsole.properties 2022-04-15 07:52:43.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=File +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Copy all Messages +webconsole.menu.copyAllMessages.accesskey=M + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Save all Messages to File +webconsole.menu.saveAllMessagesFile.accesskey=F + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/fi/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/fi/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/fi/dom/chrome/dom/dom.properties 2022-03-07 21:37:50.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/dom/chrome/dom/dom.properties 2022-04-15 07:52:43.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Kirjoita osoite. FormValidationInvalidDate=Anna kelvollinen päiväys. FormValidationInvalidTime=Anna kelvollinen aika. +FormValidationInvalidDateTime=Anna kelvollinen päiväys ja aika. +FormValidationInvalidDateMonth=Anna kelvollinen kuukausi. +FormValidationInvalidDateWeek=Anna kelvollinen viikko. FormValidationPatternMismatch=Anna arvo pyydetyssä muodossa. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Anna arvo pyydetyssä muodossa: %S. @@ -430,3 +433,6 @@ # LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". OffscreenCanvasToBlobWarning=OffscreenCanvas.toBlob() is deprecated. Use OffscreenCanvas.convertToBlob() instead. + +# LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" +# LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" diff -Nru thunderbird-91.7.0+build2/l10n/fi/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/fi/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/fi/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/mail/messenger/aboutDialog.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Mitä uutta diff -Nru thunderbird-91.7.0+build2/l10n/fi/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/fi/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/fi/mail/messenger/aboutImport.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/mail/messenger/aboutImport.ftl 2022-04-15 07:52:44.000000000 +0000 @@ -18,6 +18,11 @@ ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Tuo sovelluksesta { $app } @@ -25,11 +30,24 @@ profile-file-picker-dir = Valitse profiilikansio profile-file-picker-zip = Valitse zip-tiedosto (pienempi kuin 2 Gt) items-pane-title = Valitse tuotavat asiat +items-pane-desc = Tuo lähteestä +items-pane-source = Lähteen sijainti: items-pane-checkbox-accounts = Tilit ja asetukset items-pane-checkbox-address-books = Osoitekirjat items-pane-checkbox-calendars = Kalenterit items-pane-checkbox-mail-messages = Sähköpostiviestit +## Import from address book file steps + +addr-book-ldif-file = LDIF-tiedosto (.ldif) +addr-book-vcard-file = vCard-tiedosto (.vcf, .vcard) +addr-book-mab-file = Mork-tietokantatiedosto (.mab) +addr-book-file-picker = Valitse osoitekirjatiedosto +addr-book-directories-pane-source = Lähdetiedosto: +addr-book-import-into-new-directory = Luo uusi kansio + ## Import dialog +progress-pane-title = Tuodaan +progress-pane-finished-desc = Valmis. error-pane-title = Virhe diff -Nru thunderbird-91.7.0+build2/l10n/fi/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/fi/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/fi/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Uusi CardDAV-osoitekirja - +carddav-window-title = Uusi CardDAV-osoitekirja carddav-dialog = .buttonlabelaccept = Jatka .buttonaccesskeyaccept = a - carddav-username-label = .value = Käyttäjätunnus: .accesskey = U - carddav-location-label = .value = Sijainti: .accesskey = S carddav-location = .default-placeholder = Osoitekirjapalvelimen URL-osoite tai isäntänimi - carddav-loading = Etsitään asetuksia… carddav-known-incompatible = { $url } on yhteensopimaton { -brand-short-name }in kanssa. carddav-connection-error = Yhteyden muodostus epäonnistui. carddav-none-found = Määritetylle tilille ei löytynyt lisättäviä osoitekirjoja. carddav-already-added = Kaikki määritetyn tilin osoitekirjat on jo lisätty. - carddav-available-books = Käytettävissä olevat osoitekirjat: diff -Nru thunderbird-91.7.0+build2/l10n/fi/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/fi/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/fi/mail/messenger/preferences/preferences.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/mail/messenger/preferences/preferences.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -188,6 +188,9 @@ smooth-scrolling-label = .label = Vieritä sivua tasaisesti .accesskey = e +browsing-gtk-use-non-overlay-scrollbars = + .label = Näytä aina vierityspalkit + .accesskey = v system-integration-legend = Järjestelmään liittäminen always-check-default = .label = Tarkista aina onko { -brand-short-name } järjestelmän oletussähköpostiohjelma diff -Nru thunderbird-91.7.0+build2/l10n/fi/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/fi/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/fi/netwerk/necko.properties 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/netwerk/necko.properties 2022-04-15 07:52:43.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Cookie “%1$S” has been rejected because it is already expired. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Cookie “%1$S” has been rejected because it is in a cross-site context and its “SameSite” is “Lax” or “Strict”. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Varoitus: ‘%1$S’ on vanhennettu, käytä ‘%2$S’ diff -Nru thunderbird-91.7.0+build2/l10n/fi/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/fi/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/fi/toolkit/chrome/global/narrate.properties 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/toolkit/chrome/global/narrate.properties 2022-04-15 07:52:43.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Kuuntele back = Takaisin start = Aloita stop = Pysäytä +# %S is the keyboard shortcut for the start command +start-label = Aloita (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Pysäytä (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = K forward = Eteenpäin speed = Nopeus selectvoicelabel = Ääni: diff -Nru thunderbird-91.7.0+build2/l10n/fi/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/fi/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/fi/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -185,6 +185,14 @@ ## +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } kanava + *[other] { $channels } kanavaa + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/fi/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/fi/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/fi/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -9,10 +9,6 @@ experimental-features-css-masonry-description = Ottaa käyttöön tuen kokeelliselle CSS Masonry Layout -ominaisuudelle. Yleiskuvauksen ominaisuudesta saa englanniksi tästä selostuksesta. Palautetta voi antaa englanniksi kommentoimalla tähän GitHub-issueen tai tähän bugiraporttiin. # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. -experimental-features-css-cascade-layers = - .label = CSS: Cascade Layers -# The title of the experiment should be kept in English as it may be referenced -# by various online articles and is technical in nature. experimental-features-web-gpu2 = .label = Web API: WebGPU experimental-features-web-gpu-description2 = Tämä uusi API tarjoaaa matalan tason tuen laskennan suorittamiseen ja grafiikan piirtämiseen käyttäen käyttäjän laitteen grafiikkaprosessoria (GPU). Määrittely on vielä keskeneräinen. Lisätietoja on bugissa 1602129. @@ -93,3 +89,6 @@ experimental-features-ime-search = .label = Osoitepalkki: näytä tulokset IME-koostamisen aikana experimental-features-ime-search-description = IME (Input Method Editor, kirjoitustapaeditori) on työkalu, jonka avulla voit kirjoittaa tavallisella näppäimistöllä monimutkaisia symboleja, kuten itäaasialaisia tai intialaisia symboleja. Tämän kokeilun ottaminen käyttöön pitää osoitepalkin auki näyttäen hakutulokset ja -ehdotukset samalla, kun käytät tekstinsyöttöä IME:n avulla. Huomaa, että IME saattaa näyttää paneelin, peittäen osoitepalkin hakutulokset. Siksi tätä asetusta suositellaan vain, kun IME ei käytä tämäntyyppistä paneelia. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name }:n käyttäjäagenttitunniste 100 (User-Agent) diff -Nru thunderbird-91.7.0+build2/l10n/fi/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/fi/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/fi/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:37:51.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fi/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:52:43.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Pistoke # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Eristetty IPC-toimija ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/fr/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/fr/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/fr/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Confidentialité : évènement privé calendar-editable-item-privacy-icon-confidential = .alt = Confidentialité : n’afficher que la date et l’heure +calendar-editable-item-recurrence = + .alt = Récurrent +calendar-editable-item-recurrence-exception = + .alt = Exception de récurrence calendar-editable-item-todo-icon-task = .alt = Tâche calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/fr/chat/matrix.properties thunderbird-91.8.1+build1/l10n/fr/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/fr/chat/matrix.properties 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/chat/matrix.properties 2022-04-15 07:52:56.000000000 +0000 @@ -242,3 +242,15 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S a annulé la vérification avec la raison : %2$S message.verification.done=Vérification terminée. +message.decryptionError=Impossible de déchiffrer le contenu de ce message. Pour demander des clés de chiffrement à partir de vos autres appareils, faites un clic droit sur ce message. +message.decrypting=Déchiffrement… +message.redacted=Message effacé. + +# Label in the message context menu +message.action.requestKey=Redemander les clés +message.action.report=Signaler le message +message.action.retry=Réessayer l’envoi +message.action.cancel=Annuler le message + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. diff -Nru thunderbird-91.7.0+build2/l10n/fr/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/fr/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/fr/devtools/client/compatibility.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/devtools/client/compatibility.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (expérimental) compatibility-issue-prefixneeded = (préfixe nécessaire) compatibility-issue-deprecated-experimental = (obsolète, expérimental) - compatibility-issue-deprecated-prefixneeded = (obsolète, préfixe nécessaire) compatibility-issue-experimental-prefixneeded = (expérimental, préfixe nécessaire) compatibility-issue-deprecated-experimental-prefixneeded = (obsolète, expérimental, préfixe nécessaire) @@ -43,7 +42,14 @@ [one] { $number } occurrence *[other] { $number } occurrences } - compatibility-no-issues-found = Aucun problème de compatibilité trouvé. compatibility-close-settings-button = .title = Fermer les paramètres +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Problèmes de compatibilité avec : + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/fr/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/fr/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/fr/devtools/client/netmonitor.properties 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/devtools/client/netmonitor.properties 2022-04-15 07:52:53.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=La chaîne « %S » a été supprimée du début du contenu JSON ci-dessous + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Chaîne de requête : +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=Paramètres d’URL + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=En-têtes de requête : +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=En-têtes + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=nom + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=valeur + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Corps du message + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=charge utile + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Corps de la requête : @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Annuler +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Effacer + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Supprimer l’élément + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Retour diff -Nru thunderbird-91.7.0+build2/l10n/fr/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/fr/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/fr/devtools/client/toolbox.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/devtools/client/toolbox.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Désactiver le masquage automatique des popups +toolbox-meatball-menu-pseudo-locale-accented = Activer la langue « accentuée » +toolbox-meatball-menu-pseudo-locale-bidi = Activer la langue « bidi » ## diff -Nru thunderbird-91.7.0+build2/l10n/fr/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/fr/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/fr/devtools/client/toolbox-options.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/devtools/client/toolbox-options.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -10,19 +10,15 @@ # The heading options-select-default-tools-label = Outils de développement par défaut - # The label for the explanation of the * marker on a tool which is currently not supported # for the target of the toolbox. options-tool-not-supported-label = * Non géré pour la cible actuelle de la boîte à outils - # The label for the heading of group of checkboxes corresponding to the developer tools # added by add-ons. This heading is hidden when there is no developer tool installed by add-ons. options-select-additional-tools-label = Outils installés via modules complémentaires - # The label for the heading of group of checkboxes corresponding to the default developer # tool buttons. options-select-enabled-toolbox-buttons-label = Boutons de la boîte à outils - # The label for the heading of the radiobox corresponding to the theme options-select-dev-tools-theme-label = Thèmes @@ -30,12 +26,10 @@ # The heading options-context-inspector = Inspecteur - # The label for the checkbox option to show user agent styles options-show-user-agent-styles-label = Afficher les styles du navigateur options-show-user-agent-styles-tooltip = .title = Activer cette option affichera les styles par défaut chargés par le navigateur - # The label for the checkbox option to enable collapse attributes options-collapse-attrs-label = Tronquer les attributs DOM options-collapse-attrs-tooltip = @@ -48,13 +42,13 @@ options-default-color-unit-hex = hexadécimal options-default-color-unit-hsl = TSL(A) options-default-color-unit-rgb = RVB(A) +options-default-color-unit-hwb = HWB options-default-color-unit-name = noms de couleurs ## Style Editor section # The heading options-styleeditor-label = Éditeur de style - # The label for the checkbox that toggles autocompletion of css in the Style Editor options-stylesheet-autocompletion-label = Compléter automatiquement le CSS options-stylesheet-autocompletion-tooltip = @@ -64,12 +58,10 @@ # The heading options-screenshot-label = Comportement pour les captures d’écran - # Label for the checkbox that toggles screenshot to clipboard feature options-screenshot-clipboard-only-label = Capturer vers le presse-papiers uniquement options-screenshot-clipboard-tooltip2 = .title = Enregistre directement la capture d’écran dans le presse-papiers - # Label for the checkbox that toggles the camera shutter audio for screenshot tool options-screenshot-audio-label = Jouer un son d’obturateur d’appareil photo options-screenshot-audio-tooltip = @@ -79,7 +71,6 @@ # The heading options-sourceeditor-label = Préférences de l’éditeur - options-sourceeditor-detectindentation-tooltip = .title = Déduire l’indentation d’après le contenu source options-sourceeditor-detectindentation-label = Détecter l’indentation @@ -97,40 +88,36 @@ # The heading (this item is also used in perftools.ftl) options-context-advanced-settings = Paramètres avancés - # The label for the checkbox that toggles the HTTP cache on or off options-disable-http-cache-label = Désactiver le cache HTTP (lorsque la boîte à outils est ouverte) options-disable-http-cache-tooltip = .title = Activer cette option désactivera le cache HTTP pour l’ensemble des onglets dans lesquels la boîte à outils est ouverte. Cette option n’a aucun effet sur les service workers. - # The label for checkbox that toggles JavaScript on or off options-disable-javascript-label = Désactiver JavaScript * options-disable-javascript-tooltip = .title = Activer cette option désactivera JavaScript pour l’onglet courant. Ce paramètre sera oublié à la fermeture de l’onglet ou de la boîte à outils. - # The label for checkbox that toggles chrome debugging, i.e. the devtools.chrome.enabled preference options-enable-chrome-label = Activer le débogage du chrome du navigateur et des modules options-enable-chrome-tooltip = .title = Activer cette option vous permettra d’utiliser divers outils de développement dans le contexte du navigateur (via Outils > Développement web > Boîte à outils du navigateur) et de déboguer des modules depuis le gestionnaire de modules complémentaires - # The label for checkbox that toggles remote debugging, i.e. the devtools.debugger.remote-enabled preference options-enable-remote-label = Activer le débogage distant options-enable-remote-tooltip2 = .title = L’activation de cette option permettra de déboguer cette instance de navigateur à distance - +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Activer les formateurs personnalisés +options-enable-custom-formatters-tooltip = + .title = Activer cette option autorise les sites à définir des formateurs personnalisés pour les objets DOM # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Activer les Service Workers via HTTP (lorsque la boîte à outils est ouverte) options-enable-service-workers-http-tooltip = .title = Activer cette option activera les Service Workers via HTTP pour tous les onglets où la boîte à outils est ouverte. - # The label for the checkbox that toggles source maps in all tools. options-source-maps-label = Activer les liens vers les sources options-source-maps-tooltip = .title = En activant cette option, les sources seront liées dans les outils. - # The message shown for settings that trigger page reload options-context-triggers-page-refresh = * Pour cette session, recharge la page - # The label for the checkbox that toggles the display of the platform data in the # Profiler i.e. devtools.profiler.ui.show-platform-data a boolean preference in about:config options-show-platform-data-label = Afficher les données de la plate-forme Gecko diff -Nru thunderbird-91.7.0+build2/l10n/fr/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/fr/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/fr/dom/chrome/dom/dom.properties 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/dom/chrome/dom/dom.properties 2022-04-15 07:52:56.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Veuillez saisir une URL. FormValidationInvalidDate=Veuillez saisir une date valide. FormValidationInvalidTime=Veuillez saisir une date valide. +FormValidationInvalidDateTime=Veuillez saisir une date et une heure valides. +FormValidationInvalidDateMonth=Veuillez saisir un mois valide. +FormValidationInvalidDateWeek=Veuillez saisir une semaine valide. FormValidationPatternMismatch=Veuillez modifier la valeur pour correspondre au format demandé. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Veuillez modifier la valeur du champ pour correspondre au format demandé : %S. @@ -430,3 +433,8 @@ # LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". OffscreenCanvasToBlobWarning=OffscreenCanvas.toBlob() est obsolète. Utilisez OffscreenCanvas.convertToBlob() à la place. + +# LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" +IDBDatabaseCreateMutableFileWarning=IDBDatabase.createMutableFile() est obsolète. Si cette API est normalisée, elle le sera probablement dans le cadre de l’initiative Origin Private File System du bug https://bugzil.la/1748667. +# LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" +IDBMutableFileOpenWarning=IDBMutableFile.open() est obsolète. Si cette API est normalisée, elle le sera probablement dans le cadre de l’initiative Origin Private File System du bug https://bugzil.la/1748667. diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/aboutDialog.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Nouveautés diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/aboutImport.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/aboutImport.ftl 2022-04-15 07:52:56.000000000 +0000 @@ -10,6 +10,7 @@ import-from-app-desc = Choisir d’importer comptes, carnets d’adresses, agendas et autres données depuis : import-address-book = Importer le fichier d’un carnet d’adresses import-calendar = Importer le fichier d’un agenda +export-profile = Exporter ## Buttons @@ -19,6 +20,11 @@ ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Importer depuis { $app } @@ -26,17 +32,36 @@ profile-file-picker-dir = Sélectionnez un dossier de profil profile-file-picker-zip = Sélectionnez un fichier zip (de taille inférieure à 2 Go) items-pane-title = Sélectionnez quoi importer -items-pane-desc = Importer depuis +items-pane-source = Emplacement d’origine : items-pane-checkbox-accounts = Comptes et paramètres items-pane-checkbox-address-books = Carnets d’adresses items-pane-checkbox-calendars = Agendas items-pane-checkbox-mail-messages = Courriers +## Import from address book file steps + +import-from-addr-book-file-desc = Sélectionnez le type de fichier que vous souhaitez importer : +addr-book-csv-file = Fichier séparé par des virgules ou des tabulations (.csv, .tsv) +addr-book-ldif-file = Fichier LDIF (.ldif) +addr-book-vcard-file = Fichier vCard (.vcf, .vcard) +addr-book-mab-file = Base de données Mork (.mab) +addr-book-file-picker = Sélectionner un fichier de carnet d’adresses +addr-book-directories-pane-title = Sélectionnez le répertoire depuis lequel vous souhaitez importer : +addr-book-directories-pane-source = Fichier source : +addr-book-import-into-new-directory = Créer un nouveau répertoire + ## Import dialog progress-pane-title = Importation +progress-pane-finished-desc = Terminé. progress-pane-restart-desc = Redémarrez pour terminer l’importation. error-pane-title = Erreur error-message-zip-file-too-big = La taille du fichier zip sélectionné est supérieure à 2 Go. Veuillez d’abord l’extraire, puis importer les données à partir du dossier d’extraction. error-message-extract-zip-file-failed = Échec de l’extraction du fichier zip. Veuillez plutôt l’extraire manuellement, puis l’importer depuis le dossier extrait. error-message-failed = L’importation a échoué de manière inattendue, des informations supplémentaires peuvent être disponibles dans la console d’erreurs. + +## element + + +## Export tab + diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Nouveau carnet d’adresses CardDAV - +carddav-window-title = Nouveau carnet d’adresses CardDAV carddav-dialog = .buttonlabelaccept = Continuer .buttonaccesskeyaccept = C - carddav-username-label = .value = Nom d’utilisateur : .accesskey = N - carddav-location-label = .value = Adresse : .accesskey = A carddav-location = .default-placeholder = URL ou nom d’hôte du serveur du carnet d’adresses - carddav-loading = Recherche de la configuration… carddav-known-incompatible = { $url } est connu pour être incompatible avec { -brand-short-name }. carddav-connection-error = La connexion a échoué. carddav-none-found = Aucun carnet d’adresses n’a été trouvé pour le compte spécifié. carddav-already-added = Tous les carnets d’adresses pour le compte spécifié ont déjà été ajoutés. - carddav-available-books = Carnets d’adresses disponibles : diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -132,8 +132,8 @@ about-addressbook-details-home-address-header = Adresse personnelle about-addressbook-details-work-address-header = Adresse professionnelle about-addressbook-details-other-info-header = Autres informations -about-addressbook-prompt-to-save-title = Enregistrer les modifications ? -about-addressbook-prompt-to-save = Voulez-vous enregistrer vos modifications ? +about-addressbook-unsaved-changes-prompt-title = Modifications non enregistrées +about-addressbook-unsaved-changes-prompt = Voulez-vous enregistrer vos modifications avant de quitter la vue d’édition ? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/menubar.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/menubar.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -67,6 +67,9 @@ mail-uidensity-touch = .label = Tactile .accesskey = T +menu-spaces-toolbar-button = + .label = Barre d’espaces + .accesskey = e ## File diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:52:56.000000000 +0000 @@ -86,6 +86,12 @@ .tooltiptext = Afficher le volet des pièces jointes ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Masquer le volet des pièces jointes ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } pièce jointe + *[other] { $count } pièces jointes + } attachment-area-show = .title = Afficher le volet des pièces jointes ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -246,8 +252,36 @@ # Template +# A line of text describing how many uploaded files have been appended to this +# message. Emphasis should be on sharing as opposed to attaching. This item is +# used as a header to a list, hence the colon. +cloud-file-count-header = + { $count -> + [one] J’ai lié un fichier à ce message : + *[other] J’ai lié { $count } fichiers à ce message : + } +# A text used in a footer, instructing the reader where to find additional +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = En savoir plus sur { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = En savoir plus sur { $firstLinks } et { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Lien protégé par mot de passe +# Used in a list of stats about a specific file +# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Size - the size of the file (Size: 4.2 MB) +# Link - the link to the file (Link: https://some.provider.com) +# Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) +# Download Limit - stating the maximum allowed downloads, before the link becomes invalid +# (Download Limit: 6) +cloud-file-template-service = Service cloud : cloud-file-template-size = Taille : cloud-file-template-link = Lien : cloud-file-template-password-protected-link = Lien protégé par mot de passe : @@ -258,6 +292,7 @@ # $provider (string) - name of the online storage service that reported the error cloud-file-connection-error-title = Erreur de connexion +cloud-file-connection-error = { -brand-short-name } est hors ligne. Impossible de se connecter à { $provider }. # $provider (string) - name of the online storage service that reported the error # $filename (string) - name of the file that was uploaded and caused the error cloud-file-upload-error-with-custom-message-title = Échec de l’envoi de { $filename } à { $provider } diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/messenger.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/messenger.ftl 2022-04-15 07:52:56.000000000 +0000 @@ -169,3 +169,55 @@ ## error messages decrypt-and-copy-failures = { $failures } des { $total } messages n’ont pas pu être déchiffrés et n’ont pas été copiés. + +## Spaces toolbar + +spaces-toolbar = + .toolbarname = Barre d’espaces +spaces-toolbar-button-mail = + .title = Aller à l’onglet courrier +spaces-toolbar-button-address-book = + .title = Aller à l’onglet du carnet d’adresses +spaces-toolbar-button-calendar = + .title = Aller à l’onglet de l’agenda +spaces-toolbar-button-tasks = + .title = Aller à l’onglet des tâches +spaces-toolbar-button-chat = + .title = Aller à l’onglet de messagerie instantanée +spaces-toolbar-button-settings = + .title = Aller à l’onglet des paramètres +spaces-toolbar-button-collapse = + .title = Réduire la barre d’outils des espaces +spaces-toolbar-button-reveal = + .title = Afficher la barre d’outils des espaces +spaces-context-new-tab-item = + .label = Ouvrir dans un nouvel onglet +spaces-context-new-window-item = + .label = Ouvrir dans une nouvelle fenêtre +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Aller à { $tabName } +settings-context-open-settings-item = + .label = Ouvrir les paramètres +settings-context-open-account-settings-item = + .label = Ouvrir les paramètres du compte +settings-context-open-addons-item = + .label = Ouvrir le gestionnaire de modules complémentaires et de thèmes + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Ouvrir le menu des espaces +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/otr/add-finger.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/otr/add-finger.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Ajouter l’empreinte d’une clé OTR - +otr-add-finger-title = Ajouter l’empreinte d’une clé OTR # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Saisissez l’empreinte de la clé OTR pour { $name }. - otr-add-finger-fingerprint = Empreinte : otr-add-finger-tooltip-error = Caractère saisi invalide. Seuls les lettres ABCDEF et les chiffres sont autorisés - otr-add-finger-input = .placeholder = L’empreinte de la clé OTR longue de 40 caractères diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/otr/finger.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/otr/finger.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Fermer .title = Empreintes OTR vues précédemment - +otr-finger-title = Empreintes numériques OTR précédemment vues finger-intro = Empreintes numériques des clés OTR de précédentes conversations chiffrées de bout en bout. - finger-screen-name = .label = Contact finger-verified = .label = État de la vérification finger-fingerprint = .label = Empreinte numérique - finger-remove = .label = Supprimer les éléments sélectionnés - finger-remove-all = .label = Tout supprimer diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/otr/otrUI.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/otr/otrUI.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -16,6 +16,7 @@ finger-verify = Vérifier finger-verify-access-key = V finger-ignore = Ignorer +finger-ignore-access-key = I # Do not translate 'OTR' (name of an encryption protocol) buddycontextmenu-label = Ajouter une empreinte OTR # Variables: @@ -59,12 +60,6 @@ # Variables: # $name (String) - the screen name of a chat contact person afterauth-unverified = L’identité de { $name } n’a pas été vérifiée. -verify-title = Vérifier l’identité de votre contact -error-title = Erreur -success-title = Chiffrement de bout en bout -success-them-title = Vérifiez l’identité de votre contact -fail-title = Impossible de vérifier -waiting-title = Demande de vérification envoyée # Do not translate 'OTR' (name of an encryption protocol) # Variables: # $error (String) - contains an error message that describes the cause of the failure diff -Nru thunderbird-91.7.0+build2/l10n/fr/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/fr/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/fr/mail/messenger/preferences/preferences.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/mail/messenger/preferences/preferences.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -116,9 +116,6 @@ .label = Réinitialiser .accesskey = i default-search-engine = Moteur de recherche par défaut -add-search-engine = - .label = Ajouter depuis un fichier - .accesskey = A add-web-search-engine = .label = Ajouter… .accesskey = A @@ -196,6 +193,9 @@ smooth-scrolling-label = .label = Doux .accesskey = o +browsing-gtk-use-non-overlay-scrollbars = + .label = Toujours afficher les barres de défilement + .accesskey = d system-integration-legend = Intégration système always-check-default = .label = Toujours vérifier si { -brand-short-name } est le client de messagerie par défaut au démarrage @@ -320,12 +320,6 @@ .accesskey = o search-handler-table = .placeholder = Filtrer les types de contenu et les actions -type-column-label = - .label = Type de contenu - .accesskey = T -action-column-label = - .label = Action - .accesskey = A type-column-header = Type de contenu action-column-header = Action save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/fr/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/fr/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/fr/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:52:53.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans sérif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Quitter le mode lecture @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Jeu de couleurs claires aboutReader.toolbar.colorschemedark = Jeu de couleurs sombres aboutReader.toolbar.colorschemesepia = Jeu de couleurs sépia +aboutReader.toolbar.colorschemeauto = Jeu de couleurs automatique diff -Nru thunderbird-91.7.0+build2/l10n/fr/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/fr/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/fr/toolkit/chrome/global/narrate.properties 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/toolkit/chrome/global/narrate.properties 2022-04-15 07:52:53.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Écouter back = Revenir en arrière start = Démarrer stop = Arrêter +# %S is the keyboard shortcut for the start command +start-label = Démarrer (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Arrêter (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Avancer speed = Vitesse selectvoicelabel = Voix : diff -Nru thunderbird-91.7.0+build2/l10n/fr/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/fr/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/fr/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } image + *[other] { $frames } images + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } canal + *[other] { $channels } canaux + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/fr/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/fr/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/fr/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Barre d’adresse : afficher les résultats pendant la composition IME experimental-features-ime-search-description = Un IME (Input Method Editor, éditeur de méthode de saisie) est un outil qui permet la saisie de symboles complexes, tels que ceux utilisés pour écrire les langues indiennes ou celles d’Asie de l’Est, tout en utilisant un clavier ordinaire. Activer cette expérience conserve ouvert le panneau de la barre d’adresse qui affiche les résultats de recherche et des suggestions, pendant que l’IME est utilisé pour saisir du texte. Notez que l’IME pourrait afficher un panneau recouvrant les résultats de la barre d’adresse, c’est pourquoi cette préférence n’est suggérée que pour les IME qui n’utilisent pas ce type de panneau. +# Firefox 100 +experimental-features-firefox-100 = + .label = Chaîne « User-Agent » { -brand-product-name } 100 +experimental-features-firefox-100-description = Demander à { -brand-short-name } d’envoyer aux sites web une chaîne « User-Agent » qui prétend être la version 100 de { -brand-product-name }. Utilisez ce paramètre pour tester si les sites web cassent lorsque { -brand-short-name } atteint un numéro de version à trois chiffres. La véritable version 100 de { -brand-product-name } devrait sortir en mai 2022, donc commencez à tester vos sites web sans attendre ! diff -Nru thunderbird-91.7.0+build2/l10n/fr/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/fr/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/fr/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:38:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fr/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:52:53.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socket # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Acteur IPC en bac à sable ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/fy-NL/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Privacy: Privee barren calendar-editable-item-privacy-icon-confidential = .alt = Privacy: Allinnich tiid en datum toane +calendar-editable-item-recurrence = + .alt = Periodyk +calendar-editable-item-recurrence-exception = + .alt = Utsûndering foar periodyk calendar-editable-item-todo-icon-task = .alt = Taak calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/chat/matrix.properties thunderbird-91.8.1+build1/l10n/fy-NL/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/chat/matrix.properties 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/chat/matrix.properties 2022-04-15 07:53:04.000000000 +0000 @@ -242,3 +242,11 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S hat de ferifikaasje annulearre mei de reden: %2$S message.verification.done=Ferifikaasje foltôge. +message.decryptionError=Koe de ynhâld fan dit berjocht net ûntsiferje. Klik mei jo rjochtermûsknop op dit berjocht, om fersiferingskaaien fan jo oare apparaten oan te freegjen. +message.decrypting=Untsiferje… +message.redacted=Berjocht is bewurke. + +# Label in the message context menu +message.action.requestKey=Kaaien opnij opfreegje +message.action.redact=Redigearje +message.action.report=Berjocht rapportearje diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/compatibility.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/compatibility.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -42,7 +42,14 @@ [one] { $number } kear *[other] { $number } kear } - compatibility-no-issues-found = Gjin kompatibiliteitsproblemen fûn. compatibility-close-settings-button = .title = Ynstellingen slute +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Kompatibiliteitsproblemen yn: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/debugger.properties 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/debugger.properties 2022-04-15 07:53:02.000000000 +0000 @@ -642,6 +642,16 @@ ignoreContextItem.unignore=Boarne net mear negearje ignoreContextItem.unignore.accesskey=a +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Rigel negearje +ignoreContextItem.ignoreLine.accesskey=l + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Rigel net mear negearje +ignoreContextItem.unignoreLine.accesskey=n + # LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated # with the ignore lines context menu item ignoreContextItem.ignoreLines=Rigels negearje diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/netmonitor.properties 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/netmonitor.properties 2022-04-15 07:53:02.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=De tekenreeks ‘%S’ is fuortsmiten fan it begjin fan de hjirûnder toande JSON ôf + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Querystring: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL-parameters + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Oanfraachheaders: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Headers + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=namme + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=wearde + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Berjochttekst + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=payload + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Oanfraachynhâld: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Annulearje +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Wiskje + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Item fuortsmite + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Tebek diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/toolbox.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/toolbox.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Automatysk pop-up ferstopje útskeakelje +toolbox-meatball-menu-pseudo-locale-accented = ’Aksintuearre’ locale ynskeakelje +toolbox-meatball-menu-pseudo-locale-bidi = Locale ‘bidi’ ynskeakelje ## diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/devtools/client/toolbox-options.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/devtools/client/toolbox-options.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Remote debugging ynskeakelje options-enable-remote-tooltip2 = .title = Troch dizze opsje yn te skeakeljen kinne jo dizze browserynstallaasje op ôfstân debugge +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Oanpaste opmaakeleminten ynskeakelje +options-enable-custom-formatters-tooltip = + .title = As jo dizze opsje ynskeakelje, kinne websites oanpaste opmaakeleminten foar DOM-objekten definiearje # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Service Workers oer HTTP ynskeakelje (as wurkset iepene is) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/fy-NL/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/dom/chrome/dom/dom.properties 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/dom/chrome/dom/dom.properties 2022-04-15 07:53:04.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Jou in URL. FormValidationInvalidDate=Fier in jildige datum yn. FormValidationInvalidTime=Fier in jildige tiid yn. +FormValidationInvalidDateTime=Fier in jildige datum en tiid yn. +FormValidationInvalidDateMonth=Fier in jildige moanne yn. +FormValidationInvalidDateWeek=Fier in jildige wike yn. FormValidationPatternMismatch=Brûk it frege formaat. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Brûk it frege formaat: %S. diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/chrome/messenger/localMsgs.properties thunderbird-91.8.1+build1/l10n/fy-NL/mail/chrome/messenger/localMsgs.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/chrome/messenger/localMsgs.properties 2022-03-07 21:38:06.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/chrome/messenger/localMsgs.properties 2022-04-15 07:53:02.000000000 +0000 @@ -31,7 +31,7 @@ receivingMessages=Berjocht %1$S fan %2$S downloade # Status - connecting to host -hostContact=Kontakt mei host, ferstjoert lochynynformaasje… +hostContact=Kontakt mei server, oanmeldingsgegevens ferstjoere… # Status - no messages to download noNewMessages=Der binne gjin nije berjochten. diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/chrome/messenger/viewLog.dtd thunderbird-91.8.1+build1/l10n/fy-NL/mail/chrome/messenger/viewLog.dtd --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/chrome/messenger/viewLog.dtd 2022-03-07 21:38:06.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/chrome/messenger/viewLog.dtd 2022-04-15 07:53:02.000000000 +0000 @@ -4,7 +4,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/installer/override.properties thunderbird-91.8.1+build1/l10n/fy-NL/mail/installer/override.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/installer/override.properties 2022-03-07 21:38:06.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/installer/override.properties 2022-04-15 07:53:02.000000000 +0000 @@ -79,7 +79,7 @@ Rename="Omneame: " Skipped="Oerslein: " CopyDetails=Details nei klamboerd kopiearje -LogInstall=Loch ynstallaasjeproses +LogInstall=Ynstallaasjefoarútgong fêstlizze yn lochbestân Byte=B Kilo=K Mega=M diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/aboutDialog.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Wat is der nij diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/aboutImport.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/aboutImport.ftl 2022-04-15 07:53:04.000000000 +0000 @@ -19,6 +19,11 @@ ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Ymportearje út { $app } @@ -27,14 +32,28 @@ profile-file-picker-zip = Selektearje in zip-bestân (lytser as 2GB) items-pane-title = Selektearje wat jo ymportearje wolle items-pane-desc = Ymportearje út +items-pane-source = Boarnelokaasje: items-pane-checkbox-accounts = Accounts en ynstellingen items-pane-checkbox-address-books = Adresboeken items-pane-checkbox-calendars = Aginda’s items-pane-checkbox-mail-messages = E-mailberjochten +## Import from address book file steps + +import-from-addr-book-file-desc = Selektearje it bestânstype dat jo ymportearje wolle: +addr-book-csv-file = Komma- of tab-skieden bestân (.csv, .tsv) +addr-book-ldif-file = LDIF-bestân (.ldif) +addr-book-vcard-file = vCard-bestân (.vcf, .vcard) +addr-book-mab-file = Mork-databasebestân (.mab) +addr-book-file-picker = Adresboekbestân selektearje +addr-book-directories-pane-title = Selektearje de map dêr’t jo nei ymportearje wolle: +addr-book-directories-pane-source = Boarnebestân: +addr-book-import-into-new-directory = Nije map meitsje + ## Import dialog progress-pane-title = Ymportearje +progress-pane-finished-desc = Foltôge. progress-pane-restart-desc = Opnij starte om it ymportearjen te foltôgjen. error-pane-title = Flater error-message-zip-file-too-big = It selektearre zip-bestân is grutter as 2 GB. Pak it earst út en ymportearje it dernei út de útpakte map. diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Nij CardDAV-adresboek - +carddav-window-title = Nij CardDAV-adresboek carddav-dialog = .buttonlabelaccept = Trochgean .buttonaccesskeyaccept = T - carddav-username-label = .value = Brûkersnamme: .accesskey = B - carddav-location-label = .value = Lokaasje: .accesskey = L carddav-location = .default-placeholder = URL of hostnamme fan de adresboekserver - carddav-loading = Konfiguraasje opsykje… carddav-known-incompatible = Fan { $url } is bekend dat it net kompatibel is mei { -brand-short-name }. carddav-connection-error = Ferbining meitsje mislearre. carddav-none-found = Gjin ta te foegjen adresboeken fûn foar it opjûne account. carddav-already-added = Alle adresboeken foar it opjûne account binne al tafoege. - carddav-available-books = Beskikbere adresboeken: diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -132,8 +132,8 @@ about-addressbook-details-home-address-header = Adres about-addressbook-details-work-address-header = Wurkadres about-addressbook-details-other-info-header = Oare ynformaasje -about-addressbook-prompt-to-save-title = Wizigingen bewarje? -about-addressbook-prompt-to-save = Wolle jo jo wizigingen bewarje? +about-addressbook-unsaved-changes-prompt-title = Net bewarre wizigingen +about-addressbook-unsaved-changes-prompt = Wolle jo jo wizigingen bewarje eardat jo de bewurkingswerjefte ferlitte? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/menubar.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/menubar.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -67,6 +67,9 @@ mail-uidensity-touch = .label = Oanraking .accesskey = O +menu-spaces-toolbar-button = + .label = Taakbalke + .accesskey = T ## File diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:53:04.000000000 +0000 @@ -86,6 +86,13 @@ .tooltiptext = It bylagefinster toane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = It bylagefinster ferstopje ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } bylage + [one] { $count } bylage + *[other] { $count } bylagen + } attachment-area-show = .title = It bylagefinster toane ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -255,12 +262,17 @@ *[other] Ik haw { $count } bestannen oan dit e-mailberjocht keppele: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Mear ynfo oer { $lastLink }. - *[other] Mear ynfo oer { $firstLinks } en { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Mear ynfo oer { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Mear ynfo oer { $firstLinks } en { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Mei wachtwurd befeilige keppeling # Used in a list of stats about a specific file @@ -280,6 +292,9 @@ # Messages # $provider (string) - name of the online storage service that reported the error +cloud-file-connection-error-title = Ferbiningsflater +cloud-file-connection-error = { -brand-short-name } is offline. Koe gjin ferbining meitsje mei { $provider }. +# $provider (string) - name of the online storage service that reported the error # $filename (string) - name of the file that was uploaded and caused the error cloud-file-upload-error-with-custom-message-title = Opladen fan { $filename } nei { $provider } mislearre # $provider (string) - name of the online storage service that reported the error diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/messenger.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/messenger.ftl 2022-04-15 07:53:04.000000000 +0000 @@ -169,3 +169,55 @@ ## error messages decrypt-and-copy-failures = { $failures } fan { $total } berjochten koene net ûntsifere wurde en binne net kopiearre. + +## Spaces toolbar + +spaces-toolbar = + .toolbarname = Taakbalke +spaces-toolbar-button-mail = + .title = Wikselje nei it e-mailljepblêd +spaces-toolbar-button-address-book = + .title = Wikselje nei it adresboekljepblêd +spaces-toolbar-button-calendar = + .title = Wikselje nei it agindaljepblêd +spaces-toolbar-button-tasks = + .title = Wikselje nei it takenljepblêd +spaces-toolbar-button-chat = + .title = Wikselje nei it chatljepblêd +spaces-toolbar-button-settings = + .title = Wikselje nei it ynstellingenljepblêd +spaces-toolbar-button-collapse = + .title = Taakbalke ynklappe +spaces-toolbar-button-reveal = + .title = Taakbalke toane +spaces-context-new-tab-item = + .label = Iepenje yn nij ljepblêd +spaces-context-new-window-item = + .label = Iepenje yn nij finster +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Wikselje nei { $tabName } +settings-context-open-settings-item = + .label = Ynstellingen iepenje +settings-context-open-account-settings-item = + .label = Accountynstellingen iepenje +settings-context-open-addons-item = + .label = Add-ons en tema’s iepenje + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Taakmenu iepenje +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/otr/add-finger.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/otr/add-finger.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = OTR-fingerôfdruk tafoegje - +otr-add-finger-title = OTR-fingerôfdruk tafoegje # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = De OTR-fingerôfdruk foar { $name } tafoegje. - otr-add-finger-fingerprint = Fingerôfdruk: otr-add-finger-tooltip-error = Unjildich teken ynfierd. Allinnich sifers en de letters ABCDEF binne tastien - otr-add-finger-input = .placeholder = De 40 tekens lange OTR-fingerôfdruk diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/otr/finger.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/otr/finger.ftl 2022-04-15 07:53:03.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Slute .title = Earder besjoene OTR-fingerôfdrukken - +otr-finger-title = Earder sjoene OTR-fingerôfdrukken finger-intro = OTR-fingerôfdrukken fan eardere end-to-end-fersifere petearen. - finger-screen-name = .label = Kontakt finger-verified = .label = Ferifikaasjesteat finger-fingerprint = .label = Fingerôfdruk - finger-remove = .label = Selektearre fuortsmite - finger-remove-all = .label = Alle fuortsmite diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/mail/messenger/preferences/preferences.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/mail/messenger/preferences/preferences.ftl 2022-04-15 07:53:02.000000000 +0000 @@ -116,9 +116,6 @@ .label = Standertynstelling tebeksette .accesskey = S default-search-engine = Standertsykmasine -add-search-engine = - .label = Tafoegje út bestân - .accesskey = T add-web-search-engine = .label = Tafoegje… .accesskey = T @@ -196,6 +193,9 @@ smooth-scrolling-label = .label = Floeiend skowe brûke .accesskey = e +browsing-gtk-use-non-overlay-scrollbars = + .label = Skowbalken altyd toane + .accesskey = k system-integration-legend = Systeemyntegraasje always-check-default = .label = By it opstarten altyd neigean oft { -brand-short-name } de standert e-mailclient is @@ -320,12 +320,6 @@ .accesskey = K search-handler-table = .placeholder = Ynhâldtypen en aksjes filterje -type-column-label = - .label = Ynhâldtype - .accesskey = t -action-column-label = - .label = Aksje - .accesskey = A type-column-header = Ynhâldstype action-column-header = Aksje save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/fy-NL/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/netwerk/necko.properties 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/netwerk/necko.properties 2022-04-15 07:53:03.000000000 +0000 @@ -88,3 +88,6 @@ CookieRejectedExpired=Cookie ‘%1$S’ is wegere omdat dizze al ferrûn is. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. CookieRejectedForNonSameSiteness=Cookie ‘%1$S’ is ôfwezen, omdat dizze har yn in cross-site-context stiet en de ‘SameSite’ ‘Lax’ of ‘Strict’ is. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. +APIDeprecationWarning=Warskôging: ‘%1$S’ wurdt net mear stipe, brûk ‘%2$S’ diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:53:02.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Lêzerwerjefte slute @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Kleureskema Ljocht aboutReader.toolbar.colorschemedark = Kleureskema Donker aboutReader.toolbar.colorschemesepia = Kleureskema Sepia +aboutReader.toolbar.colorschemeauto = Kleureskema Automatysk diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/chrome/global/narrate.properties 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/chrome/global/narrate.properties 2022-04-15 07:53:03.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Harkje back = Tebek start = Starte stop = Stopje +# %S is the keyboard shortcut for the start command +start-label = Starte (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Stopje (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = H forward = Foarút speed = Faasje selectvoicelabel = Stim: diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:53:03.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } frame + *[other] { $frames } frames + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } kanaal + *[other] { $channels } kanalen + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:53:03.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Adresbalke: resultaten toane wylst opstellen mei IME experimental-features-ime-search-description = In IME (Input Method Editor) is in helpmiddel wêrmei't jo komplekse symboalen, lykas yn East-Aziatyske of Yndyske skreaune talen brûkt wurdt, mei in standert toetseboerd ynfiere kinne. As jo dit eksperimint ynskeakelje, bliuwt it adresbalkepaniel iepen, wêrby sykresultaten en -suggestjes toand wurde, wylst jo IME brûke om tekst yn te fieren. Merk op dat de IME ien paniel toane kin dat de adresbalkeresultaten ôfdekt; dêrom wurdt dizze foarkar allinnich foarsteld foar IME wêrby dit type paniel net brûkt wurdt. +# Firefox 100 +experimental-features-firefox-100 = + .label = User-Agent-tekenrige { -brand-product-name } 100 +experimental-features-firefox-100-description = Soargj derfoar dat { -brand-short-name } websites in User-Agent-tekenrige stjoert dy’t har foardocht as { -brand-product-name } ferzje 100. Brûk dizze ynstelling om te testen of websites net mear wurkje wannear’t it ferzjenûmer fan { -brand-short-name } út trije sifers bestiet. De echte { -brand-product-name } 100 stiet pland foar maaie 2022, dus begjin no mei it testen fan jo websites! diff -Nru thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/fy-NL/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:38:07.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/fy-NL/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:53:03.000000000 +0000 @@ -42,6 +42,8 @@ process-type-socket = Socket # process used to decode media process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Sandbokste IPC Actor ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/gl/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/gl/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/gl/devtools/client/toolbox.ftl 2022-03-07 21:38:23.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/gl/devtools/client/toolbox.ftl 2022-04-15 07:53:22.000000000 +0000 @@ -24,6 +24,7 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Desactivar o agachado automática de xanelas emerxente +toolbox-meatball-menu-pseudo-locale-accented = Activar a configuración rexional «acentuada». ## diff -Nru thunderbird-91.7.0+build2/l10n/gl/devtools/shared/highlighters.ftl thunderbird-91.8.1+build1/l10n/gl/devtools/shared/highlighters.ftl --- thunderbird-91.7.0+build2/l10n/gl/devtools/shared/highlighters.ftl 2022-03-07 21:38:23.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/gl/devtools/shared/highlighters.ftl 2022-04-15 07:53:22.000000000 +0000 @@ -31,6 +31,13 @@ # The layout type of an element shown in the infobar when hovering over a DOM element and # it is both a flex container and a flex item. flextype-dual = Contedor/elemento flex +# The message displayed in the content page when the user clicks on the +# "Pick an element from the page" in about:devtools-toolbox inspector panel, when +# debugging a remote page. +# Variables +# $action (string) - Will either be remote-node-picker-notice-action-desktop or +# remote-node-picker-notice-action-touch +remote-node-picker-notice = Selector de nodos DevTools activado. { $action } # Text displayed in `remote-node-picker-notice`, when the remote page is on desktop remote-node-picker-notice-action-desktop = Prema nun elemento para seleccionalo no Inspector # Text displayed in `remote-node-picker-notice`, when the remote page is on Android diff -Nru thunderbird-91.7.0+build2/l10n/he/calendar/calendar/calendar-event-dialog-reminder.ftl thunderbird-91.8.1+build1/l10n/he/calendar/calendar/calendar-event-dialog-reminder.ftl --- thunderbird-91.7.0+build2/l10n/he/calendar/calendar/calendar-event-dialog-reminder.ftl 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/calendar/calendar/calendar-event-dialog-reminder.ftl 2022-04-15 07:53:29.000000000 +0000 @@ -2,6 +2,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +calendar-event-reminder-icon-display = + .alt = הצגת התרעה calendar-event-reminder-icon-email = .alt = שליחת דוא״ל calendar-event-reminder-icon-audio = diff -Nru thunderbird-91.7.0+build2/l10n/he/calendar/calendar/calendar-ics-file-dialog.ftl thunderbird-91.8.1+build1/l10n/he/calendar/calendar/calendar-ics-file-dialog.ftl --- thunderbird-91.7.0+build2/l10n/he/calendar/calendar/calendar-ics-file-dialog.ftl 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/calendar/calendar/calendar-ics-file-dialog.ftl 2022-04-15 07:53:29.000000000 +0000 @@ -16,6 +16,18 @@ .value = פריטים נטענים… calendar-ics-file-dialog-search-input = .placeholder = סינון פריטים… +calendar-ics-file-dialog-sort-start-ascending = + .label = מיון לפי תאריך התחלה (ראשון עד אחרון) +calendar-ics-file-dialog-sort-start-descending = + .label = מיון לפי תאריך התחלה (אחרון עד ראשון) +# "A > Z" is used as a concise way to say "alphabetical order". +# You may replace it with something appropriate to your language. +calendar-ics-file-dialog-sort-title-ascending = + .label = מיון לפי כותרת (א > ת) +# "Z > A" is used as a concise way to say "reverse alphabetical order". +# You may replace it with something appropriate to your language. +calendar-ics-file-dialog-sort-title-descending = + .label = מיון לפי כותרת (ת > א) calendar-ics-file-dialog-progress-message = מתבצע ייבוא… calendar-ics-file-import-success = הייבוא הושלם בהצלחה! calendar-ics-file-import-error = אירעה שגיאה והייבוא נכשל. diff -Nru thunderbird-91.7.0+build2/l10n/he/calendar/chrome/calendar/dialogs/calendar-event-dialog-reminder.dtd thunderbird-91.8.1+build1/l10n/he/calendar/chrome/calendar/dialogs/calendar-event-dialog-reminder.dtd --- thunderbird-91.7.0+build2/l10n/he/calendar/chrome/calendar/dialogs/calendar-event-dialog-reminder.dtd 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/calendar/chrome/calendar/dialogs/calendar-event-dialog-reminder.dtd 2022-04-15 07:53:29.000000000 +0000 @@ -11,10 +11,7 @@ - - - - + diff -Nru thunderbird-91.7.0+build2/l10n/he/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/he/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/he/devtools/client/aboutdebugging.ftl 2022-03-07 21:38:29.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/devtools/client/aboutdebugging.ftl 2022-04-15 07:53:29.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = ניפוי שגיאות - הקמה - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = ניפוי שגיאות - סביבת ריצה / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = ‏{ -brand-shorter-name } זה - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = הקמה - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB מופעל - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB מושבת - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = מחובר # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = מנותק - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = לא נמצאו מכשירים - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = התחברות - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = חיבור בהקמה… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = החיבור נכשל - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = החיבור עדיין בהמתנה, נא לבדוק אם יש הודעות בדפדפן היעד - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = תם הזמן המוקצב לחיבור - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = בהמתנה לדפדפן… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = מנותק - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = תמיכה בניפוי שגיאות - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = סמל עזרה - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = רענון מכשירים @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = הקמה - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = הגדרת שיטת החיבור שתשמש אותך לניפוי שגיאות מרחוק מול המכשיר שלך. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = ניתן להשתמש ב־{ about-debugging-this-firefox-runtime-name } כדי לנפות שגיאות בהרחבות ו־service workers בגרסה זו של { -brand-shorter-name }. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = חיבור מכשיר - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = הפעלת אפשרות זו תוריד ותוסיף את רכיבי ניפוי השגיאות הנדרשים לטובת ניפוי שגיאות בעזרת Android אל { -brand-shorter-name }. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = הפעלת התקני USB - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = השבתת התקני USB - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = בעדכון… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = מופעל about-debugging-setup-usb-status-disabled = מושבת about-debugging-setup-usb-status-updating = בעדכון… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = להפעיל את התפריט של אפשרויות למפתחים במכשיר ה־Android שלך. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = להפעיל ניפוי שגיאות ב־USB בתפריט האפשרויות למפתחים של Android. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = להפעיל ניפוי שגיאות ב־USB ב־Firefox שבמכשיר ה־Android. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = לחבר את מכשיר ה־Android שלך למחשב שלך. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = בעיות בחיבור להתקן ה־USB? פתרון בעיות - # Network section of the Setup page about-debugging-setup-network = .title = מיקום רשת - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = בעיות בחיבור דרך מיקום רשת? פתרון בעיות - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = הוספה - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = עדיין לא נוספו מיקומי רשת. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = מארח - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = הסרה - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = מארח שגוי „{ $host-value }”. התבנית הנדרשת היא „שם_מארח:מספר_פתחה”. - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,42 +162,34 @@ # Title of the processes category. about-debugging-runtime-processes = .name = תהליכים - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = פרופיל ביצועים - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = תצורת הדפדפן שלך אינה תואמת ל־Service Workers. מידע נוסף - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = הדפדפן המחובר הוא בגרסה ישנה ({ $runtimeVersion }). הגרסה המינימלית ביותר הנתמכת היא ({ $minVersion }). תצורה זו אינה נתמכת ועשויה לגרום לכשל בכלי הפיתוח. נא לעדכן את הדפדפן המחובר. פתרון בעיות - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = הדפדפן המחובר יותר עדכני ({ $runtimeVersion }, מזהה בנייה { $runtimeID }) מאשר ה־{ -brand-shorter-name } שלך ({ $localVersion }, מזהה בנייה { $localID }). זוהי תצורה שאינה נתמכת ויתכן שתגרום לכלי הפיתוח להיכשל. נא לעדכן את Firefox. פתרון בעיות - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = התנתקות - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = יוצר הפרופילים - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -248,99 +200,89 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = בינתיים כלום. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = חקירה - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = טעינת תוספת זמנית… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = אירעה שגיאה במהלך התקנת ההרחבה הזמנית. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = טעינה מחדש - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = הסרה - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = סיום תסריט רקע # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = נא לבחור בקובץ manifest.json או בארכיון ‎.xpi/.zip - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = ל־WebExtension זה יש מזהה זמני. מידע נוסף - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = כתובת manifest - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = מזהה ייחודי אוניברסלי פנימי - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = מיקום - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = מזהה הרחבה - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = תסריט רקע +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = פועל +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = נעצר # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = ביטול רישום - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = נעצר - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = שירות דחיפה - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = חקירת Service Worker מושבתת כרגע עבור { -brand-shorter-name } מרובה תהליכים - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = לשונית לא טעונה במלואה ולכן לא ניתן לחקור אותה - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = תהליך ראשי - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = התהליך הראשי עבור דפדפן היעד - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = ארגז כלים מרובה תהליכים - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = התהליך הראשי ותהליכי התוכן עבור דפדפן היעד - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = סגירת הודעה - # Label text used for the error details of message component. about-debugging-message-details-label-error = פרטי שגיאה - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = פרטי אזהרה - # Label text used for default state of details of message component. about-debugging-message-details-label = פרטים diff -Nru thunderbird-91.7.0+build2/l10n/he/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/he/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/he/devtools/client/compatibility.ftl 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/devtools/client/compatibility.ftl 2022-04-15 07:53:29.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (ניסיוני) compatibility-issue-prefixneeded = (דרושה קידומת) compatibility-issue-deprecated-experimental = (הוצא משימוש, ניסיוני) - compatibility-issue-deprecated-prefixneeded = (הוצא משימוש, דרושה קידומת) compatibility-issue-experimental-prefixneeded = (ניסיוני, דרושה קידומת) compatibility-issue-deprecated-experimental-prefixneeded = (הוצא משימוש, ניסיוני, דרושה קידומת) @@ -43,7 +42,14 @@ [one] מופע אחד *[other] { $number } מופעים } - compatibility-no-issues-found = לא נמצאו בעיות תאימות. compatibility-close-settings-button = .title = סגירת הגדרות +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + בעיות תאימות ב: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/he/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/he/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/he/devtools/client/netmonitor.properties 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/devtools/client/netmonitor.properties 2022-04-15 07:53:29.000000000 +0000 @@ -161,6 +161,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → התקשרות %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=המחרוזת ״%S״ הוסרה מתחילת ה־JSON המוצג להלן + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1449,10 +1454,33 @@ # above the query string entry in the custom request form netmonitor.custom.query=מחרוזת שאילתה: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=פרמטרים של הכתובת + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=כותרי בקשה: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=כותרים + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=שם + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=ערך + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=מטען + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=גוף בקשה: @@ -1465,6 +1493,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=ביטול +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=ניקוי + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=הסרת פריט + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=חזרה diff -Nru thunderbird-91.7.0+build2/l10n/he/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/he/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/he/devtools/client/webconsole.properties 2022-03-07 21:38:29.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/devtools/client/webconsole.properties 2022-04-15 07:53:29.000000000 +0000 @@ -223,6 +223,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=קובץ +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=העתקת כל ההודעות +webconsole.menu.copyAllMessages.accesskey=ה + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=שמירת כל ההודעות לקובץ +webconsole.menu.saveAllMessagesFile.accesskey=ש + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. @@ -535,9 +548,5 @@ # shown when users select a thread that they want to evaluate an # expression for. -# LOCALIZATION NOTE (webconsole.group.cookieSameSiteLaxByDefaultEnabled): do not translate 'sameSite'. -# LOCALIZATION NOTE (webconsole.group.cookieSameSiteLaxByDefaultDisabled): do not translate 'sameSite'. - # LOCALIZATION NOTE (webconsole.group.cookieSameSiteLaxByDefaultEnabled2): do not translate 'SameSite'. # LOCALIZATION NOTE (webconsole.group.cookieSameSiteLaxByDefaultDisabled2): do not translate 'SameSite'. - diff -Nru thunderbird-91.7.0+build2/l10n/he/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/he/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/he/dom/chrome/dom/dom.properties 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/dom/chrome/dom/dom.properties 2022-04-15 07:53:29.000000000 +0000 @@ -37,6 +37,9 @@ FormValidationInvalidEmail=נא להזין כתובת דוא״ל. FormValidationInvalidURL=נא להזין כתובת. FormValidationInvalidDate=נא להכניס תאריך תקין. +FormValidationInvalidDateTime=נא להכניס תאריך ושעה תקינים. +FormValidationInvalidDateMonth=נא להכניס חודש תקין. +FormValidationInvalidDateWeek=נא להכניס שבוע תקין. FormValidationPatternMismatch=נא להתאים למבנה המבוקש. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=נא להתאים למבנה המבוקש: %S. @@ -327,3 +330,10 @@ # LOCALIZATION NOTE: Do not translate "Element.setCapture()" and "Element.setPointerCapture()"". # LOCALIZATION NOTE: Do not translate "Element.releaseCapture()" and "Element.releasePointerCapture()". # LOCALIZATION NOTE: Do not translate "Document.releaseCapture()" and "Element.releasePointerCapture()". + +# LOCALIZATION NOTE: Don't translate browser.runtime.lastError, %S is the error message from the unchecked value set on browser.runtime.lastError. + +# LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". + +# LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" +# LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" diff -Nru thunderbird-91.7.0+build2/l10n/he/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/he/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/he/mail/chrome/messenger/addons.properties 2022-03-07 21:38:29.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/mail/chrome/messenger/addons.properties 2022-04-15 07:53:29.000000000 +0000 @@ -84,6 +84,7 @@ addonInstallError-4=לא ניתן היה להתקין את %2$S מכיוון של־%1$S אין אפשרות לשנות את הקובץ הנדרש. addonInstallError-5=%1$S מנע מאתר זה להתקין תוספת לא מאומתת. addonLocalInstallError-1=לא ניתן היה להתקין תוספת זו עקב שגיאה במערכת הקבצים. +addonLocalInstallError-2=לא ניתן להתקין תוספת זו כיוון שהיא אינה תואמת את התוספת המצופה %1$S. addonLocalInstallError-3=לא ניתן היה להתקין תוספת זו מכיוון שהיא ככל הנראה פגומה. addonLocalInstallError-4=לא ניתן היה להתקין את %2$S מכיוון של־%1$S אין אפשרות לשנות את הקובץ הנדרש. addonLocalInstallError-5=לא ניתן היה להתקין תוספת זו מכיוון שהיא לא אומתה. @@ -222,6 +223,18 @@ # hosts for which this webextension is requesting permission. webextPerms.hostDescription.tooManySites=גישה לנתונים שלך באתר נוסף;גישה לנתונים שלך ב־#1 אתרים נוספים +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextSitePerms.headerWithPerms=להוסיף את %1$S? הרחבה זו מעניקה ל־%2$S את היכולות הבאות: +webextSitePerms.headerUnsignedWithPerms=להוסיף את %1$S? הרחבה זו אינה מאומתת. הרחבות זדוניות יכולות לגנוב מידע אישי או לסכן את המחשב שלך. יש להוסיף אותה רק אם הגיעה ממקור מהימן. הרחבה זו מעניקה ל־%2$S את היכולות הבאות: + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties +webextSitePerms.description.midi=גישה להתקני MIDI +webextSitePerms.description.midi-sysex=גישה להתקני MIDI עם תמיכה ב־SysEx + # LOCALIZATION NOTE (webext.defaultSearch.description) # %1$S is replaced with the localized named of the extension that is asking to change the default search engine. # %2$S is replaced with the name of the current search engine diff -Nru thunderbird-91.7.0+build2/l10n/he/mail/chrome/messenger/converterDialog.dtd thunderbird-91.8.1+build1/l10n/he/mail/chrome/messenger/converterDialog.dtd --- thunderbird-91.7.0+build2/l10n/he/mail/chrome/messenger/converterDialog.dtd 2022-03-07 21:38:29.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/mail/chrome/messenger/converterDialog.dtd 2022-04-15 07:53:29.000000000 +0000 @@ -6,5 +6,6 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/he/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/he/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/he/mail/messenger/preferences/preferences.ftl 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/mail/messenger/preferences/preferences.ftl 2022-04-15 07:53:29.000000000 +0000 @@ -56,8 +56,8 @@ .label = אפשרויות סמל היישום… .accesskey = ס animated-alert-label = - .label = הראה התרעה - .accesskey = א + .label = הצגת התרעה + .accesskey = ה customize-alert-label = .label = התאמה אישית… .accesskey = ה @@ -88,6 +88,9 @@ smooth-scrolling-label = .label = שימוש בגלילה חלקה .accesskey = ח +browsing-gtk-use-non-overlay-scrollbars = + .label = תמיד להציג פסי גלילה + .accesskey = פ system-integration-legend = השתלבות במערכת always-check-default = .label = בדוק בכל הפעלה אם { -brand-short-name } היא תוכנת דואר ברירת המחדל @@ -205,12 +208,6 @@ quoted-text-color = .label = צבע: .accesskey = ב -type-column-label = - .label = סיווג תוכן - .accesskey = ס -action-column-label = - .label = פעולה - .accesskey = פ save-to-label = .label = שמור קבצים אל .accesskey = ש diff -Nru thunderbird-91.7.0+build2/l10n/he/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/he/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/he/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:53:29.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aaאבג aboutReader.toolbar.close=סגירת תצוגת הקריאה @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = ערכת צבעים בהירה aboutReader.toolbar.colorschemedark = ערכת צבעים כהה aboutReader.toolbar.colorschemesepia = ערכת צבעים חמה +aboutReader.toolbar.colorschemeauto = ערכת צבעים אוטומטית diff -Nru thunderbird-91.7.0+build2/l10n/he/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/he/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/he/toolkit/chrome/global/narrate.properties 2022-03-07 21:38:30.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/he/toolkit/chrome/global/narrate.properties 2022-04-15 07:53:29.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = האזנה back = חזרה start = התחלה stop = עצירה +# %S is the keyboard shortcut for the start command +start-label = הפעלה (%S) +# %S is the keyboard shortcut for the stop command +stop-label = עצירה (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = ה forward = קדימה speed = מהירות selectvoicelabel = קול: diff -Nru thunderbird-91.7.0+build2/l10n/hr/chat/matrix.properties thunderbird-91.8.1+build1/l10n/hr/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/hr/chat/matrix.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/chat/matrix.properties 2022-04-15 07:53:35.000000000 +0000 @@ -12,12 +12,16 @@ # These are the protocol specific options shown in the account manager and # account wizard windows. options.saveToken=Token za pristup trgovini +options.deviceDisplayName=Naziv za prikaz uređaja +options.homeserver=Poslužitelj # LOCALIZATION NOTE (options.encryption.*): # These are strings used to build the status information of the encryption # storage, shown in the account manager. %S is one of the statuses and the # strings are combined with a pipe (|) between. +options.encryption.statusOk=u redu +options.encryption.statusNotOk=nije spremno # %1$S is the session ID, %2$S is the session display name # LOCALIZATION NOTE (connection.*): @@ -32,6 +36,9 @@ # LOCALIZATION NOTE (connection.error.*): # These will show in the account manager if an error occurs during the # connection attempt. +connection.error.noSupportedFlow=Poslužitelj ne nudi kompatibilni tijek prijave. +connection.error.authCancelled=Prekinuli ste proces autorizacije. +connection.error.sessionEnded=Sesija je odjavljena. # LOCALIZATION NOTE (chatRoomField.*): # These are the name of fields displayed in the 'Join Chat' dialog diff -Nru thunderbird-91.7.0+build2/l10n/hr/devtools/client/components.properties thunderbird-91.8.1+build1/l10n/hr/devtools/client/components.properties --- thunderbird-91.7.0+build2/l10n/hr/devtools/client/components.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/devtools/client/components.properties 2022-04-15 07:53:35.000000000 +0000 @@ -22,3 +22,14 @@ # LOCALIZATION NOTE (notificationBox.closeTooltip): The content of a tooltip that # appears when hovering over the close button in a notification box. notificationBox.closeTooltip=Zatvori ovu poruku + +# LOCALIZATION NOTE (appErrorBoundary.description): This is the information displayed +# once the panel errors. +# %S represents the name of panel which has the crash. + +# LOCALIZATION NOTE (appErrorBoundary.fileBugButton): This is the text that appears in +# the button to visit the bug filing link. +appErrorBoundary.fileBugButton=Izvještaj o grešci datoteke + +# LOCALIZATION NOTE (appErrorBoundary.reloadPanelInfo): This is the text that appears +# after the panel errors to instruct the user to reload the panel. diff -Nru thunderbird-91.7.0+build2/l10n/hr/devtools/client/markers.properties thunderbird-91.8.1+build1/l10n/hr/devtools/client/markers.properties --- thunderbird-91.7.0+build2/l10n/hr/devtools/client/markers.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/devtools/client/markers.properties 2022-04-15 07:53:35.000000000 +0000 @@ -33,7 +33,7 @@ marker.label.cycleCollection.forgetSkippable=CC graph redukcija marker.label.timestamp=Vremenska oznaka marker.label.worker=Radni proces -marker.label.messagePort=MessagePort +marker.label.messagePort=Priključak poruka marker.label.unknown=Nepoznato # LOCALIZATION NOTE (marker.label.javascript.*): @@ -135,4 +135,3 @@ # The name of a nursery collection. marker.nurseryCollection=Nursery skupljanje - diff -Nru thunderbird-91.7.0+build2/l10n/hr/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/hr/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/hr/devtools/client/netmonitor.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/devtools/client/netmonitor.properties 2022-04-15 07:53:35.000000000 +0000 @@ -91,6 +91,9 @@ # available for shown. responseEmptyText=Za ovaj zahtjev nema podataka o odgovoru +# LOCALIZATION NOTE (paramsNoPayloadText): This is the text displayed in the +# request tab of the network details pane when there are no params available. + # LOCALIZATION NOTE (paramsFilterText): This is the text displayed in the # request tab of the network details pane for the filtering input. paramsFilterText=Filtriraj parametre zahtjeva @@ -843,6 +846,9 @@ # in the action bar's search tab netmonitor.actionbar.search=Traži +# LOCALIZATION NOTE (netmonitor.actionbar.HTTPCustomRequest): This is the label displayed +# in the action bar's edit and resend tab + # LOCALIZATION NOTE (messagesTruncated): This is the text displayed # in the messages panel when the number of messages is over the # truncation limit. @@ -993,6 +999,9 @@ # in the network toolbar for the search button. netmonitor.toolbar.search=Traži +# LOCALIZATION NOTE (netmonitor.toolbar.HTTPCustomRequest): This is the tooltip label displayed +# in the network toolbar for the new HTTP Custom Request button. + # LOCALIZATION NOTE (netmonitor.toolbar.resetColumns): This is the label # displayed in the network table header context menu. netmonitor.toolbar.resetColumns=Obnovi stupce @@ -1066,6 +1075,13 @@ # on the button in the headers tab that toggle view for raw request/response headers # from the currently displayed request +# LOCALIZATION NOTE (netmonitor.headers.blockedByCORS): This is the message displayed +# in the notification shown when a request has been blocked by CORS with a more +# specific reason shown in the parenthesis + +#LOCALIZATION NOTE (netmonitor.headers.blockedByCORSTooltip): This is the tooltip +# displayed on the learnmore link of the blocked by CORS notification. + # LOCALIZATION NOTE (netmonitor.response.name): This is the label displayed # in the network details response tab identifying an image's file name or font face's name. netmonitor.response.name=Naziv: @@ -1326,6 +1342,7 @@ # LOCALIZATION NOTE (netmonitor.context.importHar.accesskey): This is the access key # for the Import HAR menu item displayed in the context menu for a network panel +netmonitor.context.importHar.accesskey=I # LOCALIZATION NOTE (netmonitor.har.importHarDialogTitle): This is a label # used for import file open dialog @@ -1422,6 +1439,12 @@ # above the request headers entry in the custom request form netmonitor.custom.headers=Zaglavlja zahtjeva: +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Tijelo zahtjeva: @@ -1434,6 +1457,9 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Odustani +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Natrag @@ -1525,4 +1551,3 @@ netmonitor.errorpanel.fileBugButton=Podnesi izvještaj o grešci # LOCALIZATION NOTE (netmonitor.errorpanel.reloadPanelInfo): This is the text that appears after Network panel errors to instruct the user to reload the panel. - diff -Nru thunderbird-91.7.0+build2/l10n/hr/devtools/client/performance.properties thunderbird-91.8.1+build1/l10n/hr/devtools/client/performance.properties --- thunderbird-91.7.0+build2/l10n/hr/devtools/client/performance.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/devtools/client/performance.properties 2022-04-15 07:53:35.000000000 +0000 @@ -108,7 +108,7 @@ # LOCALIZATION NOTE (recordingsList.importDialogTitle): # This string is displayed as a title for importing a recoring from disk. -recordingsList.importDialogTitle=Učitavanje snimke… +recordingsList.importDialogTitle=Uvezi snimku … # LOCALIZATION NOTE (recordingsList.saveDialogTitle): # This string is displayed as a title for saving a recording to disk. diff -Nru thunderbird-91.7.0+build2/l10n/hr/devtools/client/tooltips.ftl thunderbird-91.8.1+build1/l10n/hr/devtools/client/tooltips.ftl --- thunderbird-91.7.0+build2/l10n/hr/devtools/client/tooltips.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/devtools/client/tooltips.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -15,29 +15,17 @@ ## $display (string) - A CSS display value e.g. "inline-block". inactive-css-not-grid-or-flex-container = { $property } ne utječe na ovaj element, budući da nije niti fleks-kontejner niti grid-kontejner. - inactive-css-not-grid-or-flex-container-or-multicol-container = { $property } ne utječe na ovaj element, budući da nije fleks-kontejner, grid-kontejner ili višestupčani kontejner. - inactive-css-not-grid-or-flex-item = { $property } ne utječe na ovaj element, budući da nije mrežni ili fleks element. - inactive-css-not-grid-item = { $property } ne utječe na ovaj element, budući da nije mrežni element. - inactive-css-not-grid-container = { $property } ne utječe na ovaj element, budući da nije grid-kontejner. - inactive-css-not-flex-item = { $property } ne utječe na ovaj element, budući da nije fleks element. - inactive-css-not-flex-container = { $property } ne utječe na ovaj element, budući da nije fleks-kontejner. - inactive-css-not-inline-or-tablecell = { $property } ne utječe na ovaj element, budući da nije linijski element ili ćelija tablice. - inactive-css-property-because-of-display = { $property } ne utječe na ovaj element, budući da sadrži prikaz { $display }. - inactive-css-not-display-block-on-floated = Vrijednost za display promijenjena je u block jer je element postavljen na float. - inactive-css-property-is-impossible-to-override-in-visited = Zbog ograničenja :visited nije moguće nadjačati { $property }. - inactive-css-position-property-on-unpositioned-box = { $property } ne utječe na ovaj element, budući da nije pozicionirani element. - inactive-text-overflow-when-no-overflow = { $property } ne utječe na ovaj element, budući da overflow:hidden nije postavljeno. ## In the Rule View when a CSS property cannot be successfully applied we display @@ -45,29 +33,17 @@ ## the problem can be solved. inactive-css-not-grid-or-flex-container-fix = Pokušaj dodati display:grid ili display:flex. { learn-more } - inactive-css-not-grid-or-flex-container-or-multicol-container-fix = Pokušaj dodati display:grid, display:flex ili columns:2. { learn-more } - inactive-css-not-grid-or-flex-item-fix-2 = Pokušaj dodati display:grid, display:flex, display:inline-grid ili display:inline-flex. { learn-more } - inactive-css-not-grid-item-fix-2 = Pokušaj dodati display:grid ili display:inline-grid nadređenom elementu stavke. { learn-more } - inactive-css-not-grid-container-fix = Pokušaj dodati display:grid ili display:inline-grid. { learn-more } - inactive-css-not-flex-item-fix-2 = Pokušaj dodati display:flex ili display:inline-flex nadređenom elementu stavke. { learn-more } - inactive-css-not-flex-container-fix = Pokušaj dodati display:flex ili display:inline-flex. { learn-more } - inactive-css-not-inline-or-tablecell-fix = Pokušaj dodati display:inline ili display:table-cell. { learn-more } - inactive-css-non-replaced-inline-or-table-row-or-row-group-fix = Pokušaj dodati display:inline-block ili display:block. { learn-more } - inactive-css-non-replaced-inline-or-table-column-or-column-group-fix = Pokušaj dodati display:inline-block. { learn-more } - inactive-css-not-display-block-on-floated-fix = Pokušaj ukloniti float ili dodati display:block. { learn-more } - inactive-css-position-property-on-unpositioned-box-fix = Pokušaj postaviti svojstvo position na nešto što nije static. { learn-more } - inactive-text-overflow-when-no-overflow-fix = Pokušaj dodati overflow:hidden. { learn-more } ## In the Rule View when a CSS property may have compatibility issues with other browsers @@ -77,8 +53,11 @@ ## $property (string) - A CSS declaration name e.g. "-moz-user-select" that can be a platform specific alias. ## $rootProperty (string) - A raw CSS property name e.g. "user-select" that is not a platform specific alias. +css-compatibility-default-message = Svojstvo { $property } nije podržano u sljedećim preglednicima: +css-compatibility-deprecated-experimental-message = Svojstvo { $property } je bilo eksperimentalno svojstvo koje je sada zastarjelo prema W3C standardima. Nije podržano u sljedećim preglednicima: +css-compatibility-deprecated-experimental-supported-message = Svojstvo { $property } je bilo eksperimentalno svojstvo koje je sada zastarjelo prema W3C standardima. +css-compatibility-deprecated-message = Svojstvo { $property } je sada zastarjelo prema W3C standardima. Nije podržano u sljedećim preglednicima: +css-compatibility-deprecated-supported-message = Svojstvo { $property } je zastarjelo prema W3C standardima. css-compatibility-experimental-message = { $property } je eksperimentalno svojstvo. Nije podržano u sljedećim preglednicima: - css-compatibility-experimental-supported-message = { $property } je eksperimentalno svojstvo. - css-compatibility-learn-more-message = Saznaj više o { $rootProperty } diff -Nru thunderbird-91.7.0+build2/l10n/hr/dom/chrome/appstrings.properties thunderbird-91.8.1+build1/l10n/hr/dom/chrome/appstrings.properties --- thunderbird-91.7.0+build2/l10n/hr/dom/chrome/appstrings.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/dom/chrome/appstrings.properties 2022-04-15 07:53:35.000000000 +0000 @@ -18,7 +18,7 @@ notCached=Ovaj dokument više nije dostupan. netOffline=Ovaj dokument ne može biti prikazan u izvanmrežnom radu. Za rad u mreži, odznačite Izvanmrežni rad u Datoteka izborniku. isprinting=Dokument se ne može mijenjati dok se ispisuje ili dok je u Pregledu prije ispisa. -deniedPortAccess=Pristup broju izlaza je onemogućen zbog sigurnosnih razloga. +deniedPortAccess=Pristup navedenom broju priključka deaktiviran je iz sigurnosnih razloga. proxyResolveFailure=Konfigurirani proxy poslužitelj nije pronađen. Provjeri postavke i pokušaj ponovo. proxyConnectFailure=Veza je odbijena prilikom pokušaja spajanja na konfigurirani proxy poslužitelj. Provjeri postavke i pokušaj ponovo. contentEncodingError=Nije moguće prikazati stranicu koju pokušavaš otvoriti, jer koristi nepostojeće ili nepodržane oblike komprimiranja. diff -Nru thunderbird-91.7.0+build2/l10n/hr/dom/chrome/netError.dtd thunderbird-91.8.1+build1/l10n/hr/dom/chrome/netError.dtd --- thunderbird-91.7.0+build2/l10n/hr/dom/chrome/netError.dtd 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/dom/chrome/netError.dtd 2022-04-15 07:53:35.000000000 +0000 @@ -10,8 +10,8 @@ Iako je ime stranice ispravno, preglednik nije u stanju uspostaviti vezu.

  • Možda je stranica privremeno nedostupna? Pokušaj ponovo kasnije.
  • Možeš li pregledati druge stranice? Provjeri mrežne postavke računala.
  • Je li tvoje računalo ili mreža zaštićena vatrozidom ili proxyem? Neispravne postavke mogu onemogućiti pregledavanje interneta.
"> - -Zatražena adresa ima definiran ulaz (npr. mozilla.org:80 za ulaz 80 na mozilla.org) koji se inače koristi za druge radnje, a ne pretraživanje. Pretraživač je prekinuo zahtjev za tvoje zaštite i sigurnosti.

"> + +Zatražena adresa je odredila priključak (npr. mozilla.org:80 za priključak 80 na mozilla.org) koji se inače koristi za druge radnje koje ne pretražuju internet. Pretraživač je prekinuo zahtjev radi tvoje zaštite i sigurnosti.

"> Preglednik nije pronašao poslužitelja za navedenu adresu.

  • Je li adresa krivo upisana? (npr. ww.mozilla.org umjesto wwwmozilla.org)
  • Je li ova domena stvarno postoji? Možda joj je istekla registracija.
  • Ne možeš pregledati druge stranice? Provjeri mrežne postavke i postavke DNS poslužitelja.
  • Je li tvoje računalo zaštićeno vatrozidom ili proxyem? Neispravne postavke mogu onemogućiti pregledavanje.
"> diff -Nru thunderbird-91.7.0+build2/l10n/hr/dom/chrome/security/csp.properties thunderbird-91.8.1+build1/l10n/hr/dom/chrome/security/csp.properties --- thunderbird-91.7.0+build2/l10n/hr/dom/chrome/security/csp.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/dom/chrome/security/csp.properties 2022-04-15 07:53:35.000000000 +0000 @@ -87,7 +87,7 @@ # %1$S is the ignored src # %2$S is the directive which supports src IgnoringSourceWithinDirective = Zanemaruje se izvor '%1$S' (ne podržava se unutar ‘%2$S’). - + # CSP Errors: # LOCALIZATION NOTE (couldntParseInvalidSource): # %1$S is the source that could not be parsed @@ -97,7 +97,7 @@ couldntParseInvalidHost = Nije moguće obraditi neispravan poslužitelj %1$S # LOCALIZATION NOTE (couldntParsePort): # %1$S is the string source -couldntParsePort = Nije moguće obraditi port u %1$S +couldntParsePort = Nije moguće obraditi priključak u %1$S # LOCALIZATION NOTE (duplicateDirective): # %1$S is the name of the duplicate directive duplicateDirective = Otkrivena je dvostruka uputa %1$S. Zanemarit će se sva pojavljivanja osim prvog. diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/hr/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/hr/mail/chrome/messenger/addons.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/chrome/messenger/addons.properties 2022-04-15 07:53:35.000000000 +0000 @@ -107,7 +107,6 @@ # %S is brandShortName webextPerms.experimentWarning=Zlonamjerni dodaci mogu ukrasti vaše privatne podatke ili ugroziti vaše računalo. Instalirajte ovaj dodatak samo ukoliko vjerujete izvoru. - webextPerms.headerWithPerms=Dodati %S? Ovo proširenje imat će dozvole za: webextPerms.headerUnsigned=Dodati %S? Ovo proširenje nije provjereno. Zlonamjerna proširenja mogu ukrasti tvoje privatne podatke ili ugroziti računalo. Dodaj ga samo ako vjeruješ njegovom izvoru. webextPerms.headerUnsignedWithPerms=Dodati %S? Ovo proširenje nije provjereno. Zlonamjerna proširenja mogu ukrasti tvoje privatne podatke ili ugroziti računalo. Dodaj ga samo ako vjeruješ njegovom izvoru. Ovo proširenje imat će dozvole za: @@ -226,6 +225,18 @@ # hosts for which this webextension is requesting permission. webextPerms.hostDescription.tooManySites=Pristup vašim podacima na još #1 stranici;Pristup vašim podacima na još #1 stranice;Pristup vašim podacima na još #1 stranica +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & +webextSitePerms.headerWithPerms=Dodaj %1$S? Ovaj dodatak daje sljedeće mogućnosti %2$S: +webextSitePerms.headerUnsignedWithPerms=Dodaj %1$S? Ovo proširenje nije provjereno. Zlonamjerna proširenja mogu ukrasti tvoje privatne podatke ili ugroziti računalo. Dodaj ga samo ako vjeruješ njegovom izvoru. Ovo proširenje daje sljedeće mogućnosti %2$S: + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties +webextSitePerms.description.midi=Pristup MIDI uređajima +webextSitePerms.description.midi-sysex=Pristup MIDI uređajima sa SysEx podrškom + # LOCALIZATION NOTE (webext.defaultSearch.description) # %1$S is replaced with the localized named of the extension that is asking to change the default search engine. # %2$S is replaced with the name of the current search engine @@ -235,4 +246,3 @@ webext.defaultSearchYes.accessKey=D webext.defaultSearchNo.label=Ne webext.defaultSearchNo.accessKey=N - diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/aboutRights.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/aboutRights.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/aboutRights.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/aboutRights.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -18,6 +18,7 @@ rights-intro-point-6 = Da bi mogao reproducirati neke vrste video zapisa, { -brand-short-name } preuzima određene module za dekripciju od trećih strana. rights-webservices-header = { -brand-full-name }ove informacijske usluge na webu rights-webservices = { -brand-full-name } koristi web-bazirane usluge („Usluge”) kako bi se omogućile neke funkcije koje možeš koristiti s ovom binarnom verzijom { -brand-short-name }a pod uvjetima koji su dolje navedeni. Ako ne želiš koristiti jednu ili više usluga ili, ako su ti uslovi korištenja neprihvatljivi, možeš onemogućiti funkciju ili usluge. Instrukcije o tome, kako onemogućiti određenu funkciju ili uslugu, možeš pronaći ovdje. Druge funkcije i usluge mogu biti onemogućene u postavkama aplikacije. +rights-webservices2 = { -brand-full-name } koristi web-bazirane usluge („Usluge”) kako bi se omogućile neke funkcije koje možeš koristiti s ovom binarnom verzijom { -brand-short-name }a pod uvjetima koji su dolje navedeni. Ako ne želiš koristiti jednu ili više usluga ili, ako su ti uslovi korištenja neprihvatljivi, možeš onemogućiti funkciju ili usluge. Instrukcije o tome, kako onemogućiti određenu funkciju ili uslugu, možeš pronaći ovdje. Druge funkcije i usluge mogu biti onemogućene u postavkama aplikacije. rights-locationawarebrowsing = Geolokacijsko pregledavanje: je uvijek dobrovoljno. Podaci o lokaciji se nikada ne šalju bez tvojeg dopuštenja. Ako želiš u potpunosti onemogućiti ovu mogućnost, slijedi ove korake: rights-locationawarebrowsing-term-1 = U adresnu traku upišite about:config rights-locationawarebrowsing-term-2 = Upiši geo.enabled diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/accountCentral.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/accountCentral.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/accountCentral.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/accountCentral.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,58 +4,44 @@ account-central-title = Dobro došli u { -brand-full-name } account-settings = Postavke računa - # $accounts (Number) - the number of configured accounts setup-title = Odaberi što želiš postaviti about-title = O { -brand-full-name }u resources-title = Resursi - release-notes = .title = O { -brand-full-name }u - email-label = E-mail .aria-label = Poveži se na postojeći e-mail račun email-description = { -brand-short-name } omogućuje povezivanje s postojećim e-mail računom za jednostavno i učinkovito čitanje e-pošte u aplikaciji. - calendar-label = Kalendar .aria-label = Stvori novi kalendar calendar-description = { -brand-short-name } omogućuje rukovanje događajima za dobru organiziranost. Ako se povežeš s udaljenim kalendarom, svi će se događaji sinkronizirati na svim tvojim uređajima. - chat-label = Chat .aria-label = Poveži se na svoj chat račun chat-description = { -brand-short-name } omogućuje povezivanje s više računa za trenutnu razmjenu poruka, nudeći podršku za razne platforme. - filelink-label = Filelink .aria-label = Postavi Filelink filelink-description = { -brand-short-name } omogućuje postavljanje prikladnog Filelink računa u oblaku za jednostavno slanje velikih privitaka. - addressbook-label = Adresar .aria-label = Stvori novi adresar addressbook-description = { -brand-short-name } omogućuje organiziranje svih kontakata u adresaru. Možeš se povezati i s udaljenim adresarom za sinkroniziranje svih tvojih kontakata. - feeds-label = Feedovi .aria-label = Poveži se na feedove feeds-description = { -brand-short-name } omogućuje povezivanje s RSS/Atom feedovima za primanje vijesti i aktualiziranja. - newsgroups-label = Interesne grupe .aria-label = Poveži se na interesne grupe newsgroups-description = { -brand-short-name } omogućuje povezivanje sa svim mogućim interesnim grupama. - import-title = Uvezi iz jednog drugog programa import-paragraph = { -brand-short-name } omogućuje uvoz poruka e-pošte, kontakata adresara, pretplata na feedove, postavki i/ili filtera iz drugih programa za e-poštu kao i uobičajenih formata adresara. - +import-paragraph2 = { -brand-short-name } omogućuje uvoz poruka e-pošte, kontakata adresara, pretplata na feedove, postavki i/ili filtera iz drugih programa za e-poštu kao i uobičajenih formata adresara. import-label = Uvoz .aria-label = Uvezi podatke iz drugih programa - about-paragraph = Thunderbird je vodeći program za e-poštu i kalendare, otvorenog koda, dostupan na više platformi, besplatan za poslovno i privatno korištenje. Želimo da ostane siguran i postane još bolji. Donacija će nam omogućiti da zaposlimo programere, platimo za infrastrukturu i nastavimo poboljšavati Thunderbird. - about-paragraph-consider-donation = Thunderbird financiraju korisnici poput tebe! Ako ti se sviđa Thunderbird, molimo te da doniraš.Najbolji način na koji možeš osigurati da Thunderbird ostane dostupan je putem donacije. - explore-link = Istraži funkcije support-link = Podrška involved-link = Uključi se developer-link = Dokumentacija programera - read = Pročitane poruke compose = Piši novu poruku search = Pretraži poruke diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/accountcreation/accountSetup.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/accountcreation/accountSetup.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/accountcreation/accountSetup.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/accountcreation/accountSetup.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -2,38 +2,56 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + ## Header + ## Form fields ## Action buttons + ## Notifications + ## Illustrations + ## Results area +account-setup-result-imap-description = Držite vaše mape i poruke e-pošte sinkronizirane na svom poslužitelju +account-setup-result-pop-description = Držite vaše mape i poruke e-pošte na svom računalu + ## Error messages + ## Manual configuration area + ## Incoming/Outgoing SSL Authentication options + ## Incoming/Outgoing SSL options + ## Warning insecure server dialog + ## Warning Exchange confirmation dialog + ## Dismiss account creation dialog + ## Alert dialogs + ## Addon installation section + ## Success view + ## Calendar synchronization dialog diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/accountManager.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/accountManager.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/accountManager.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/accountManager.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -3,6 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. open-preferences-sidebar-button = { -brand-short-name } postavke +open-preferences-sidebar-button2 = { -brand-short-name } postavke open-addons-sidebar-button = Dodaci i teme account-action-add-newsgroup-account = .label = Dodaj račun interesnih grupa… diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,11 +4,10 @@ carddav-window = .title = Novi CardDAV adresar - +carddav-window-title = Novi CardDAV adresar carddav-dialog = .buttonlabelaccept = Nastavi .buttonaccesskeyaccept = N - carddav-username-label = .value = Korisničko ime .accesskey = K @@ -17,11 +16,9 @@ .accesskey = L carddav-location = .default-placeholder = URL ili naziv poslužitelja gdje se nalazi adresar - carddav-loading = Traženje konfiguracije … carddav-known-incompatible = Poznato je da { $url } nije kompatibilan s { -brand-short-name }. carddav-connection-error = Neuspjelo povezivanje. carddav-none-found = Nije pronađen nijedan adresar za navedeni račun. carddav-already-added = Svi adresari za navedeni račun već su dodani. - carddav-available-books = Dostupni adresari: diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -140,3 +140,13 @@ about-addressbook-details-other-info-header = Druge informacije about-addressbook-prompt-to-save-title = Spremi promjene? about-addressbook-prompt-to-save = Želite li spremiti promjene? + +# Photo dialog + +about-addressbook-photo-drop-target = Ispustite ili zalijepite sliku ovdje ili kliknite da odaberete datoteku. +about-addressbook-photo-drop-loading = Učitavanje fotografije… +about-addressbook-photo-drop-error = Učitavanje fotografije nije uspjelo. +about-addressbook-photo-filepicker-title = Odaberite slikovnu datoteku +about-addressbook-photo-discard = Odbaci postojeću fotografiju +about-addressbook-photo-cancel = Odustani +about-addressbook-photo-save = Spremi diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/chat.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/chat.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/chat.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/chat.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,18 +4,36 @@ chat-joining-chat-icon2 = .alt = Pridruživanje razgovoru - chat-left-chat-icon2 = .alt = Napustio razgovor - chat-participant-owner-role-icon2 = .alt = Vlasnik - chat-participant-administrator-role-icon2 = .alt = Administrator - chat-participant-moderator-role-icon2 = .alt = Moderator - chat-participant-voiced-role-icon2 = .alt = Sudionici mogu slati poruke +chat-verify-identity = + .label = Provjerite identitet + .accesskey = i +chat-identity-verified = + .label = Identitet je već provjeren +chat-buddy-identity-status = Povjerenje u šifriranje +chat-buddy-identity-status-verified = Provjereno +chat-buddy-identity-status-unverified = Neprovjereno + +## Conversation invite notification box + +# This string appears in a notification bar at the top of the Contacts window +# when someone invited the user to a multi user chat conversation, to request +# the user to confirm they want to join the chat. +# Variables: +# $conversation (String) - Name of the conversation the user is invited to. +chat-conv-invite-label = Pozvani ste na razgovor u { $conversation } +chat-conv-invite-accept = + .label = Prihvati + .accesskey = a +chat-conv-invite-deny = + .label = Odbaci + .accesskey = O diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/chat-verifySession.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/chat-verifySession.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/chat-verifySession.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/chat-verifySession.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -0,0 +1,14 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +verify-window-title = Provjerite identitet +# Variables: +# $subject (String) - a human readable identifier for the other side of the verification flow. +verify-window-subject-title = Provjerite identitet { $subject } +verify-dialog = + .buttonlabelaccept = Podudaraju se + .buttonaccesskeyaccept = P + .buttonlabelextra2 = Ne podudaraju se + .buttonaccesskeyextra2 = N +challenge-label = Provjerite da li prikazani niz odgovara prikazu na drugom kraju. diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/exportDialog.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/exportDialog.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/exportDialog.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/exportDialog.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -8,7 +8,7 @@ .buttonlabelaccept = Dalje export-dialog-button-finish = Završi export-dialog-file-picker = Izvoz u zip datoteku -export-dialog-desc1 = Izvezite račune e-pošte, poruke e-pošte, adresare i postavke u zip datoteku. +export-dialog-description1 = Izvezite račune e-pošte, poruke e-pošte, adresare i postavke u zip datoteku. export-dialog-desc2 = Po potrebi, možete uvesti zip datoteku kako biste obnovili svoj profil. export-dialog-exporting = Izvoz… export-dialog-exported = Izvezeno! diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/importDialog.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/importDialog.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/importDialog.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/importDialog.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,9 +4,18 @@ # Short name of the import module thunderbird-import-name = Thunderbird - # Description of the import module thunderbird-import-description = Uvezite poštu iz Thunderbird profilne mape. - +import-from-thunderbird-zip = + .label = Thunderbird (izvezena sigurnosna kopija profila; zip datoteka manja od 2GB) + .accesskey = z +import-from-thunderbird-dir = + .label = Thunderbird (mapa profila) + .accesskey = T import-select-profile-zip = Odaberite komprimiranu mapu profila - +import-select-profile-dir = Odaberite mapu profila +zip-file-too-big-title = Zip datoteka je prevelika +zip-file-too-big-message = Odabrana zip datoteka veća je od 2GB. Prvo je raspakirajte, a zatim uvezite iz odredišne mape. +wizardpage-failed = + .label = Uvoz nije uspio +wizardpage-failed-message = Uvoz neočekivano nije uspio, više informacija može biti dostupno u konzoli grešaka. diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/menubar.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/menubar.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/menubar.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/menubar.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -2,6 +2,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +toolbar-context-menu-menu-bar = + .toolbarname = Traka izbornika + .accesskey = T ## Tools Menu @@ -10,6 +13,9 @@ menu-tools-preferences = .label = Postavke .accesskey = P +menu-tools-settings = + .label = Postavke + .accesskey = e menu-addons-and-themes = .label = Dodaci i teme .accesskey = a @@ -61,6 +67,9 @@ mail-uidensity-touch = .label = Za dodir .accesskey = Z +menu-spaces-toolbar-button = + .label = Alatna traka zbijenosti + .accesskey = s ## File diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -3,9 +3,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Addressing widget +## Addressing widget # $type (String) - the type of the addressing row +remove-address-row-button = + .title = Ukloni { $type } polje +# $type (String) - the type of the addressing row # $count (Number) - the number of address pills currently present in the addressing row address-input-type-aria-label = { $count -> @@ -14,7 +17,6 @@ [few] { $type } s { $count } adrese, koristi tipku lijeve strelice za fokusiranje na njih. *[other] { $type } s { $count } adresa, koristi tipku lijeve strelice za fokusiranje na njih. } - # $email (String) - the email address # $count (Number) - the number of address pills currently present in the addressing row pill-aria-label = @@ -23,25 +25,57 @@ [few] { $email }, 1 od { $count }: pritisni Enter za uređivanje, Delete za uklanjanje. *[other] { $email }, 1 od { $count }: pritisni Enter za uređivanje, Delete za uklanjanje. } - +# $email (String) - the email address +pill-tooltip-invalid-address = { $email } nije valjana adresa e-pošte +# $email (String) - the email address +pill-tooltip-not-in-address-book = { $email } nije u vašem adresaru pill-action-edit = .label = Uredi adresu .accesskey = e - pill-action-move-to = .label = Premjesti se na Prima .accesskey = t - pill-action-move-cc = .label = Premjesti se na Cc .accesskey = c - pill-action-move-bcc = .label = Premjesti se na Bcc .accesskey = B - -# Attachment widget - +pill-action-expand-list = + .label = Proširi popis + .accesskey = P + +## Attachment widget + +ctrl-cmd-shift-pretty-prefix = + { PLATFORM() -> + [macos] ⇧ ⌘{ " " } + *[other] Ctrl+Shift+ + } +trigger-attachment-picker-key = A +toggle-attachment-pane-key = M +menuitem-toggle-attachment-pane = + .label = Okno privitka + .accesskey = p + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key } +toolbar-button-add-attachment = + .label = Priloži + .tooltiptext = Dodajte privitak ({ ctrl-cmd-shift-pretty-prefix }{ trigger-attachment-picker-key }) +add-attachment-notification-reminder = + .label = Dodaj privitak… + .tooltiptext = { toolbar-button-add-attachment.tooltiptext } +add-attachment-notification-reminder2 = + .label = Dodaj privitak… + .accesskey = a + .tooltiptext = { toolbar-button-add-attachment.tooltiptext } +menuitem-attach-files = + .label = Datoteke… + .accesskey = D + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ trigger-attachment-picker-key } +context-menuitem-attach-files = + .label = Priloži datoteke… + .accesskey = P + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ trigger-attachment-picker-key } # $count (Number) - the number of attachments in the attachment bucket attachment-bucket-count = .value = @@ -52,64 +86,129 @@ *[other] { $count } priloga } .accesskey = r - +expand-attachment-pane-tooltip = + .tooltiptext = Prikaži okno privitka ({ ctrl-cmd-shift-pretty-prefix } { toggle-attachment-pane-key }) +collapse-attachment-pane-tooltip = + .tooltiptext = Sakrij okno privitka ({ ctrl-cmd-shift-pretty-prefix } { toggle-attachment-pane-key }) +attachment-area-show = + .title = Prikaži okno privitka ({ ctrl-cmd-shift-pretty-prefix } { toggle-attachment-pane-key }) +attachment-area-hide = + .title = Sakrij okno privitka ({ ctrl-cmd-shift-pretty-prefix } { toggle-attachment-pane-key }) drop-file-label-attachment = { $count -> [one] Dodaj kao privitak [few] Dodaj kao privitke *[other] Dodaj kao privitke } +drop-file-label-inline = + { $count -> + [one] Umetni ugrađeno + [few] Umetni ugrađeno + *[other] Umetni ugrađeno + } -# Reorder Attachment Panel +## Reorder Attachment Panel +move-attachment-first-panel-button = + .label = Premjesti na prvo +move-attachment-left-panel-button = + .label = Premjesti lijevo +move-attachment-right-panel-button = + .label = Premjesti desno +move-attachment-last-panel-button = + .label = Premjesti na zadnje button-return-receipt = .label = Potvrda .tooltiptext = Zatraži potvrdu za ovu poruku -# Encryption +## Encryption + +message-to-be-signed-icon = + .alt = Potpiši poruku +message-to-be-encrypted-icon = + .alt = Šifriraj poruku -# Addressing Area +## Addressing Area to-compose-address-row-label = .value = Prima - # $key (String) - the shortcut key for this field to-compose-show-address-row-menuitem = .label = { to-compose-address-row-label.value } polje - .accesskey = T + .accesskey = P .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } - to-compose-show-address-row-label = .value = { to-compose-address-row-label.value } .tooltiptext = Prikaži { to-compose-address-row-label.value } polje ({ to-compose-show-address-row-menuitem.acceltext }) - cc-compose-address-row-label = .value = Cc - # $key (String) - the shortcut key for this field cc-compose-show-address-row-menuitem = .label = { cc-compose-address-row-label.value } polje .accesskey = C .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } - cc-compose-show-address-row-label = .value = { cc-compose-address-row-label.value } .tooltiptext = Prikaži { cc-compose-address-row-label.value } polje ({ cc-compose-show-address-row-menuitem.acceltext }) - bcc-compose-address-row-label = .value = Bcc - # $key (String) - the shortcut key for this field bcc-compose-show-address-row-menuitem = .label = { bcc-compose-address-row-label.value } polje .accesskey = B .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } - bcc-compose-show-address-row-label = .value = { bcc-compose-address-row-label.value } .tooltiptext = Prikaži { bcc-compose-address-row-label.value } polje ({ bcc-compose-show-address-row-menuitem.acceltext }) - - +# $count (Number) - the count of addresses in the "To" and "Cc" fields. +many-public-recipients-info = { $count } primatelja u Prima i Cc će vidjeti sve adrese. Možete izbjeći ovo ukoliko koristite Bcc polje. +to-address-row-label = + .value = Prima +# $key (String) - the shortcut key for this field +show-to-row-main-menuitem = + .label = Prima polje + .accesskey = P + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } +# No acceltext should be shown. +# The label should match the show-to-row-button text. +show-to-row-extra-menuitem = + .label = Prima + .accesskey = P +# $key (String) - the shortcut key for this field +show-to-row-button = Prima + .title = Prikaži Prima polje ({ ctrl-cmd-shift-pretty-prefix }{ $key }) +cc-address-row-label = + .value = Cc +# $key (String) - the shortcut key for this field +show-cc-row-main-menuitem = + .label = Cc polje + .accesskey = C + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } +# No acceltext should be shown. +# The label should match the show-cc-row-button text. +show-cc-row-extra-menuitem = + .label = Cc + .accesskey = C +# $key (String) - the shortcut key for this field +show-cc-row-button = Cc + .title = Prikaži Cc polje ({ ctrl-cmd-shift-pretty-prefix }{ $key }) +bcc-address-row-label = + .value = Bcc +# $key (String) - the shortcut key for this field +show-bcc-row-main-menuitem = + .label = Bcc polje + .accesskey = B + .acceltext = { ctrl-cmd-shift-pretty-prefix }{ $key } +# No acceltext should be shown. +# The label should match the show-bcc-row-button text. +show-bcc-row-extra-menuitem = + .label = Bcc + .accesskey = B +# $key (String) - the shortcut key for this field +show-bcc-row-button = Bcc + .title = Prikaži Bcc polje ({ ctrl-cmd-shift-pretty-prefix }{ $key }) +extra-address-rows-menu-button = + .title = Ostala polja adresiranja za prikaz many-public-recipients-bcc = .label = Koristi Bcc umjesto toga .accesskey = u @@ -122,3 +221,12 @@ # Tools + +## FileLink + + +# Template + + +# Messages + diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/messenger.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/messenger.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -2,29 +2,192 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +## Window controls + +messenger-window-minimize-button = + .tooltiptext = Smanji +messenger-window-maximize-button = + .tooltiptext = Proširi +messenger-window-restore-down-button = + .tooltiptext = Vrati dolje +messenger-window-close-button = + .tooltiptext = Zatvori +# Variables: +# $count (Number) - Number of unread messages. +unread-messages-os-tooltip = + { $count -> + [one] { $count } nepročitana poruka + [few] { $count } nepročitane poruke + *[other] { $count } nepročitanih poruka + } about-rights-notification-text = { -brand-short-name } je slobodan softver otvorenog koda, izgrađen od tisuće ljudi iz cijelog svijeta. ## Content tabs +content-tab-page-loading-icon = + .alt = Stranica se učitava +content-tab-security-high-icon = + .alt = Veza je sigurna +content-tab-security-broken-icon = + .alt = Veza nije sigurna + ## Toolbar +addons-and-themes-toolbarbutton = + .label = Dodaci i teme + .tooltiptext = Upravljajte svojim dodacima +quick-filter-toolbarbutton = + .label = Brzo filtriranje + .tooltiptext = Filtriranje poruka +redirect-msg-button = + .label = Preusmjeri + .tooltiptext = Preusmjeri odabrane poruke + ## Folder Pane +folder-pane-toolbar = + .toolbarname = Alatna traka okna mapa + .accesskey = m +folder-pane-toolbar-options-button = + .tooltiptext = Mogućnosti okna mapa +folder-pane-header-label = Mape + ## Folder Toolbar Header Popup +folder-toolbar-hide-toolbar-toolbarbutton = + .label = Sakrij alatnu traku + .accesskey = k +show-all-folders-label = + .label = Sve mape + .accesskey = a +show-unread-folders-label = + .label = Nepročitane mape + .accesskey = N +show-favorite-folders-label = + .label = Omiljene mape + .accesskey = O +show-smart-folders-label = + .label = Ujedinjene mape + .accesskey = U +show-recent-folders-label = + .label = Nedavne mape + .accesskey = N +folder-toolbar-toggle-folder-compact-view = + .label = Zbijeni prikaz + .accesskey = Z + ## Menu +redirect-msg-menuitem = + .label = Preusmjeri + .accesskey = u +menu-file-save-as-file = + .label = Datoteka… + .accesskey = D + ## AppMenu +# Since v89 we dropped the platforms distinction between Options or Preferences +# and consolidated everything with Preferences. +appmenu-preferences = + .label = Postavke +appmenu-save-as-file = + .label = Datoteka… +appmenu-settings = + .label = Postavke +appmenu-addons-and-themes = + .label = Dodaci i teme +appmenu-help-enter-troubleshoot-mode = + .label = Način rada za rješavanje problema… +appmenu-help-exit-troubleshoot-mode = + .label = Isključi način rada za rješavanje problema +appmenu-help-more-troubleshooting-info = + .label = Više informacija za rješavanje problema +appmenu-redirect-msg = + .label = Preusmjeri + ## Context menu +context-menu-redirect-msg = + .label = Preusmjeri +mail-context-delete-messages = + .label = + { $count -> + [one] Obriši odabrane poruke + [few] Obriši odabrane poruke + *[other] Obriši odabrane poruke + } +context-menu-decrypt-to-folder = + .label = Kopiraj kao dešifrirano u + .accesskey = p + ## Message header pane +other-action-redirect-msg = + .label = Preusmjeri +message-header-msg-flagged = + .title = Zvjezdica + .aria-label = Zvjezdica +message-header-msg-not-flagged = + .title = Bez zvjezdice + .aria-label = Bez zvjezdice + ## Action Button Context Menu +toolbar-context-menu-manage-extension = + .label = Upravljanje dodatkom + .accesskey = e +toolbar-context-menu-remove-extension = + .label = Ukloni dodatak + .accesskey = U + ## Message headers +message-header-address-in-address-book-icon = + .alt = Adresa je u adresaru +message-header-address-not-in-address-book-icon = + .alt = Adresa nije u adresaru + ## Add-on removal warning +# Variables: +# $name (String): The name of the addon that will be removed. +addon-removal-title = Ukloni { $name }? +addon-removal-confirmation-button = Ukloni +addon-removal-confirmation-message = Ukloniti { $name } kao i njegovu konfiguraciju i podatke iz { -brand-short-name }? +caret-browsing-prompt-title = Pokazivačko pregledavanje +caret-browsing-prompt-text = Pritiskom na F7, uključujete ili isključujete Pokazivačko pregledavanje. To znači da će se na sadržaju pojaviti kursor koji vam omogućava označavanje teksta tipkovnicom. Želite li uključiti Pokazivačko pregledavanje? +caret-browsing-prompt-check-text = Ne pitaj ponovno. +repair-text-encoding-button = + .label = Ispravi kodiranje teksta + .tooltiptext = Pogodi ispravno kodiranje teksta iz sadržaja poruke + ## no-reply handling +no-reply-title = Odgovor nije podržan +no-reply-message = Čini se da adresa za odgovor ({ $email }) nije nadzirana adresa. Poruke poslane na ovu adresu vjerojatno nitko neće pročitati. +no-reply-reply-anyway-button = Svejedno odgovori + +## error messages + +decrypt-and-copy-failures = { $failures } od { $total } poruka nije moglo biti dešifrirano i nije kopirano. + +## Spaces toolbar + +spaces-toolbar = + .toolbarname = Alatna traka zbijenosti +spaces-toolbar-button-mail = + .title = Prebaci na karticu poruka +spaces-toolbar-button-address-book = + .title = Prebaci na karticu adresara +spaces-toolbar-button-calendar = + .title = Prebaci na karticu kalendara +spaces-toolbar-button-tasks = + .title = Prebaci na karticu zadataka +spaces-toolbar-button-chat = + .title = Prebaci na karticu razgovora +spaces-toolbar-button-settings = + .title = Prebaci na karticu postavki +spaces-toolbar-button-collapse = + .title = Zatvori alatnu traku zbijenosti diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/migration.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/migration.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/migration.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/migration.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -0,0 +1,15 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. + +migration-progress-header = Pripremanje { -brand-short-name }a… + +## Migration tasks + + +# These strings are displayed to the user if a migration is taking a long time. +# They should be short (no more than a handful of words) and in the present tense. + +migration-task-test-fast = Testiranje brze promjene +migration-task-test-slow = Testiranje spore promjene +migration-task-test-progress = Testiranje trake napretka diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/otr/auth.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/otr/auth.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/otr/auth.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/otr/auth.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -5,33 +5,36 @@ otr-auth = .title = Potvrdi identitet kontakta .buttonlabelaccept = Potvrdi - # Variables: # $name (String) - the screen name of a chat contact person auth-title = Potvrdi identitet od { $name } - # Variables: # $own_name (String) - the user's own screen name auth-your-fp-value = Digitalni otisak za tebe, { $own_name }: - # Variables: # $their_name (String) - the screen name of a chat contact auth-their-fp-value = Digitalni otisak za { $their_name }: - auth-help = Provjera identiteta kontakta pomaže kako biste bili sigurni da je razgovor stvarno privatan, i uvelike otežava trećim stranama prisluškivanje ili manipulaciju razgovora. - +auth-help-title = Pomoć prilikom provjere +auth-question-received = Ovo je pitanje koje je postavio tvoj kontakt: auth-yes = .label = Da - auth-no = .label = Ne - auth-verified = Provjerio sam da je ovo ispravan otisak prsta. - +auth-manual-verification = Ručna provjera digitalnog otiska +auth-question-and-answer = Pitanje i odgovor +auth-shared-secret = Dijeljena tajna +auth-manual-verification-label = + .label = { auth-manual-verification } +auth-question-and-answer-label = + .label = { auth-question-and-answer } +auth-shared-secret-label = + .label = { auth-shared-secret } +auth-manual-instruction = Kontaktirajte osobu s kojom želite voditi razgovor putem drugog komunikacijskog kanala kao što su OpenPGP potpisane poruke e-pošte ili preko telefona. Obavijestite jedan drugoga o svojim otiscima prstiju. (Otisak prstiju je kontrolni zbroj koji identificira ključ za kriptiranje.) Ukoliko otisak prsta odgovara trebate označiti u razgovoru da ste provjerili otisak prsta. auth-how = Kako želite provjeriti identitet vašeg kontakta? - +auth-qa-instruction = Zamislite pitanje na koje odgovor zna samo vaš kontakt. Unesite pitanje i odgovor, te sačekajte sugovornika da unese odgovor. Ukoliko se odgovori ne podudaraju, komunikacijski kanal je možda pod nadzorom. +auth-secret-instruction = Zamislite tajnu poznatu samo vama i vašem kontaktu. Nemojte koristiti istu Internet vezu za razmjenu tajne. Unesite tajnu i čekajte svoj kontakt da je isto unese. Ukoliko se tajne ne podudaraju, komunikacijski kanal je možda pod nadzorom. auth-question = Upiši pitanje: - auth-answer = Upiši odgovor (pazi na velika/mala slova): - auth-secret = Upiši tajnu: diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/otr/otr.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/otr/otr.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/otr/otr.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/otr/otr.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -2,17 +2,71 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-encryption-required-part1 = Pokušali ste poslati ne kriptiranu poruku prema { $name }. Ne kriptirane poruke nisu dozvoljene prema postavkama. +msgevent-encryption-required-part2 = Pokušaj započinjanja privatnog razgovora. Vaše poruke će biti ponovno poslane kada započne privatni razgovor. +msgevent-encryption-error = Došlo je do greške prilikom kriptiranja poruke. Poruka nije poslana. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-connection-ended = { $name } je već zatvorio kriptiranu vezu sa vama. Kako bi izbjegli slučajno slanje ne kriptiranih poruka, vaša poruka nije poslana. Završite svoj kriptirani razgovor ili ga ponovno pokrenite. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-setup-error = Došlo je do pogreške prilikom postavljanja privatnog razgovora s { $name }. +# Do not translate 'OTR' (name of an encryption protocol) +msgevent-msg-reflected = Primate svoje OTR poruke. Ili želite razgovarati sami sa sobom ili vam netko vraća vaše poruke nazad. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-msg-resent = Zadnja poruka prema { $name } je ponovno poslana. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-not-private = Kriptirana poruka primljena od { $name } nije čitljiva jer trenutno ne komunicirate privatno. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-unreadable = Primili ste nečitljivu kriptiranu poruku od { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-malformed = Primili ste deformirane podatke poruke od { $name }. +# A Heartbeat is a technical message used to keep a connection alive. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-log-heartbeat-rcvd = Otkucaj primljen od { $name }. +# A Heartbeat is a technical message used to keep a connection alive. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-log-heartbeat-sent = Otkucaj poslan { $name }. +# Do not translate 'OTR' (name of an encryption protocol) +msgevent-rcvdmsg-general-err = Neočekivana greška se javila prilikom pokušaja zaštite razgovora koristeći OTR. +# Variables: +# $name (String) - the screen name of a chat contact person +# $msg (string) - the message that was received. +msgevent-rcvdmsg-unencrypted = Sljedeća poruka primljena od { $name } nije kriptirana: { $msg } +# Do not translate 'OTR' (name of an encryption protocol) +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-unrecognized = Primili ste neprepoznatljivu OTR poruku od { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +msgevent-rcvdmsg-for-other-instance = { $name } je poslao/a poruku namijenjenu drugoj sesiji. Ukoliko ste se više puta prijavili, druga sesija možda je primila poruku. +# Variables: +# $name (String) - the screen name of a chat contact person +context-gone-secure-private = Započeo je privatan razgovor s { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +context-gone-secure-unverified = Započeo je kriptirani, ali neprovjereni razgovor s { $name }. +# Variables: +# $name (String) - the screen name of a chat contact person +context-still-secure = Uspješno je osvježen kriptirani razgovor s { $name }. error-enc = Došlo je do greške prilikom kriptiranja poruke. - +# Variables: +# $name (String) - the screen name of a chat contact person +error-not-priv = Poslali ste kriptirane podatke { $name }, koji ih nije očekivao. error-unreadable = Poslali ste nečitljivu kriptiranu poruku. error-malformed = Poslali ste deformiranu podatkovnu poruku. - resent = [ponovno pošalji] - # Variables: # $name (String) - the screen name of a chat contact person tlv-disconnected = { $name } je završio svoj kriptirani razgovor s vama, trebali biste učiniti isto. - # Do not translate "Off-the-Record" and "OTR" which is the name of an encryption protocol # Make sure that this string does NOT contain any numbers, e.g. like "3". # Variables: diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/otr/otrUI.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/otr/otrUI.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/otr/otrUI.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/otr/otrUI.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -6,69 +6,60 @@ refresh-label = Osvježi kriptirani razgovor auth-label = Provjerite identitet vašeg kontakta reauth-label = Ponovno provjerite identitet kontakta - auth-cancel = Odustani - +auth-cancel-access-key = O auth-error = Došlo je do greške prilikom provjere identiteta vašeg kontakta. auth-success = Uspješno je završena provjera identiteta vašeg kontakta. +auth-success-them = Vaš kontakt je uspješno provjerio vaš identitet. Možda biste željeli i vi provjeriti njihov identitet postavljanjem svojih pitanja. auth-fail = Neuspješna provjera identiteta vašeg kontakta. auth-waiting = Čekanje kontakta da završi provjeru… - finger-verify = Provjeri - +finger-verify-access-key = v +finger-ignore = Zanemari +finger-ignore-access-key = i # Do not translate 'OTR' (name of an encryption protocol) buddycontextmenu-label = Dodaj OTR otisak - # Variables: # $name (String) - the screen name of a chat contact person alert-start = Pokušaj započinjanja kriptiranog razgovora s { $name }. - # Variables: # $name (String) - the screen name of a chat contact person alert-refresh = Pokušaj osvježavanja kriptiranog razgovora s { $name }. - +# Variables: +# $name (String) - the screen name of a chat contact person +alert-gone-insecure = Završio je kriptirani razgovor s { $name }. # Variables: # $name (String) - the screen name of a chat contact person finger-unseen = Identitet { $name } još uvijek nije provjeren. Slučajno prisluškivanje nije moguće, ali uz određeni napor netko bi mogao prisluškivati. Spriječite prisluškivanje provjerom identiteta kontakta. - # Variables: # $name (String) - the screen name of a chat contact person finger-seen = { $name } vas kontaktira s neprepoznatog računala. Slučajno prisluškivanje nije moguće, ali uz određeni napor netko bi mogao prisluškivati. Spriječite prisluškivanje provjerom identiteta kontakta. - +state-not-private = Trenutni razgovor nije privatan. +state-generic-not-private = Trenutni razgovor nije privatan. # Variables: # $name (String) - the screen name of a chat contact person state-unverified = Trenutni razgovor je kriptiran, ali nije privatan pošto identitet { $name } nije provjeren. - +state-generic-unverified = Trenutni razgovor je kriptiran, ali nije privatan pošto neki identiteti nisu još provjereni. # Variables: # $name (String) - the screen name of a chat contact person state-private = Identitet { $name } je provjeren. Trenutni razgovor je kriptiran i privatan. - +state-generic-private = Trenutni razgovor je kriptiran i privatan. # Variables: # $name (String) - the screen name of a chat contact person state-finished = { $name } je završio svoj kriptirani razgovor s vama, trebali biste učiniti isto. - +state-not-private-label = Nesigurno state-unverified-label = Neprovjereno state-private-label = Privatno state-finished-label = Završeno - # Variables: # $name (String) - the screen name of a chat contact person verify-request = { $name } traži provjeru tvog identiteta. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-private = Potvrdio/la si identitet { $name }. - # Variables: # $name (String) - the screen name of a chat contact person afterauth-unverified = Identitet { $name } nije provjeren. - -verify-title = Provjeri identitet kontakta -error-title = Greška -success-title = Obostrano šifriranje -fail-title = Nije moguće provjeriti -waiting-title = Poslan je zahtjev za provjeru - # Do not translate 'OTR' (name of an encryption protocol) # Variables: # $error (String) - contains an error message that describes the cause of the failure diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/preferences/am-im.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/preferences/am-im.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/preferences/am-im.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/preferences/am-im.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,4 +4,18 @@ account-settings-title = Postavke autentifikacije account-channel-title = Zadani kanali +chat-autologin = + .label = Prijavi se prilikom pokretanja chat-encryption-generic = Općenito +chat-encryption-log = + .label = Uključi potpuno šifrirane poruke u zapis razgovora +chat-encryption-label = Izvorno potpuno šifriranje +chat-encryption-description = { $protocol } pruža potpuno šifriranje za poruke razgovora. Ovo onemogućava treće strane u prisluškivanju razgovora. Dodatno postavljanje će možda biti potrebno niže za funkcioniranje šifriranja. +chat-encryption-status = Status šifriranja +chat-encryption-placeholder = Šifriranje nije inicijalizirano. +chat-encryption-sessions = Sesije +chat-encryption-sessions-description = Za potpuno šifriranje da radi ispravno, morate vjerovati drugim sesijama trenutno prijavljenim u vaš račun. Interakcija s drugim klijentima je potrebna za provjeru sesije. Provjera sesije može dovesti do toga da { -brand-short-name } također ima povjerenja u sve sesije za koje vjeruje . +chat-encryption-session-verify = provjeri + .title = Provjeri identitet ove sesije +chat-encryption-session-trusted = pouzdano + .title = Identitet ove sesije je provjeren diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/preferences/dock-options.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/preferences/dock-options.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/preferences/dock-options.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/preferences/dock-options.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -21,3 +21,4 @@ .label = Broj novih poruka .accesskey = n notification-settings-info = Možete onemogućiti značku u okviru obavijesti u postavkama sustava. +notification-settings-info2 = Možete onemogućiti značku u okviru obavijesti u postavkama sustava. diff -Nru thunderbird-91.7.0+build2/l10n/hr/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/hr/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/hr/mail/messenger/preferences/preferences.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/mail/messenger/preferences/preferences.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,111 +4,72 @@ close-button = .aria-label = Zatvori - preferences-doc-title = Postavke - +preferences-doc-title2 = Postavke category-list = .aria-label = Kategorije - pane-general-title = Općenito category-general = .tooltiptext = { pane-general-title } - pane-compose-title = Sastavljanje category-compose = .tooltiptext = Sastavljanje - pane-privacy-title = Privatnost i sigurnost category-privacy = .tooltiptext = Privatnost i sigurnost - pane-chat-title = Razgovor category-chat = .tooltiptext = Razgovor - pane-calendar-title = Kalendar category-calendar = .tooltiptext = Kalendar - general-language-and-appearance-header = Jezik i izgled - general-incoming-mail-header = Dolazna pošta - general-files-and-attachment-header = Datoteke i privici - general-tags-header = Oznake - general-reading-and-display-header = Čitanje i prikaz - general-updates-header = Ažuriranja - general-network-and-diskspace-header = Mreža i diskovni prostor - general-indexing-label = Indeksiranje - composition-category-header = Sastavljanje - composition-attachments-header = Privici - composition-spelling-title = Pravopis - compose-html-style-title = HTML stil - composition-addressing-header = Adresiranje - privacy-main-header = Privatnost - privacy-passwords-header = Lozinke - privacy-junk-header = Neželjena pošta - collection-header = { -brand-short-name } – prikupljanje i upotreba podataka - collection-description = Želimo ti omogućiti izbor i prikupljamo samo onoliko koliko nam treba da omogućimo i unaprijedimo { -brand-short-name } za sve. Uvijek pitamo za dozvolu prije nego što počnemo primati osobne podatke. collection-privacy-notice = Napomena o privatnosti - collection-health-report-telemetry-disabled = Više ne dopuštaš { -vendor-short-name }u snimanje tehničkih podataka i podataka o interakciji. Svi stari podaci bit će izbrisani u roku od 30 dana. collection-health-report-telemetry-disabled-link = Saznaj više - collection-health-report = .label = Dozvoli { -brand-short-name }u slati tehničke podatke i podatke o interakcijama organizaciji { -vendor-short-name } .accesskey = r collection-health-report-link = Saznaj više - # This message is displayed above disabled data sharing options in developer builds # or builds with no Telemetry support available. collection-health-report-disabled = Izvještavanje podataka je deaktivirano za ovu konfiguraciju izgradnje - collection-backlogged-crash-reports = .label = Dozvoli { -brand-short-name }u slati zapise o rušenju u tvoje ime .accesskey = z collection-backlogged-crash-reports-link = Saznaj više - privacy-security-header = Sigurnost - privacy-scam-detection-title = Otkrivanje prevara - privacy-anti-virus-title = Antivirus - privacy-certificates-title = Certifikati - chat-pane-header = Razgovor - chat-status-title = Status - chat-notifications-title = Obavijesti - chat-pane-styling-header = Stilsko oblikovanje - choose-messenger-language-description = Odaberite jezike koji će se koristiti za prikaz izbornika, poruka i obavijesti u { -brand-short-name }. manage-messenger-languages-button = .label = Postavi alternative… .accesskey = o confirm-messenger-language-change-description = Ponovno pokrenite { -brand-short-name } kako biste primjenili ove izmjene confirm-messenger-language-change-button = Primjeni i ponovno pokreni - update-setting-write-failure-title = Pogreška prilikom spremanju postavki ažuriranja - # Variables: # $path (String) - Path to the configuration file # The newlines between the main text and the line containing the path is @@ -117,16 +78,12 @@ { -brand-short-name } je naišao na pogrešku i nije spremio ovu promjenu. Uzmite u obzir da postavljanje postavki za ovo ažuriranje zahtjeva dozvole za pisanje u niže navedenu datoteku. Vi ili vaš administrator sustava možda ste u mogućnosti otkloniti ovu grešku tako da dozvolite grupi korisnika potpunu kontrolu nad ovom datotekom. Nije moguće pisati u datoteku: { $path } - update-in-progress-title = Ažuriranje u tijeku - update-in-progress-message = Želiš li da { -brand-short-name } nastavi s ovim ažuriranjem? - update-in-progress-ok-button = O&dbaci # Continue is the cancel button so pressing escape or using a platform standard # method of closing the UI will not discard the update. update-in-progress-cancel-button = &Nastavi - account-button = Postavke računa open-addons-sidebar-button = Dodaci i teme @@ -134,13 +91,11 @@ # This message can be seen by trying to add a Primary Password. primary-password-os-auth-dialog-message-win = Za stvaranje glavne lozinke, upiši svoje podatke za prijavu na Windows. To pomaže u zaštiti vaših računa. - # This message can be seen by trying to add a Primary Password. # The macOS strings are preceded by the operating system with "Thunderbird is trying to " # and includes subtitle of "Enter password for the user "xxx" to allow this." These # notes are only valid for English. Please test in your locale. primary-password-os-auth-dialog-message-macosx = stvori glavnu lozinku - # Don't change this label. master-password-os-auth-dialog-caption = { -brand-full-name } @@ -150,32 +105,30 @@ .key = f focus-search-shortcut-alt = .key = k - general-legend = { -brand-short-name } početna stranica - start-page-label = .label = Kad se { -brand-short-name } pokrene, prikaži početnu stranicu u prostoru za poruke .accesskey = K - location-label = .value = Lokacija: .accesskey = o restore-default-label = .label = Vrati zadano .accesskey = r - default-search-engine = Zadani pretraživač -add-search-engine = - .label = Dodaj iz datoteke +add-web-search-engine = + .label = Dodaj… .accesskey = a remove-search-engine = .label = Ukloni .accesskey = U - +add-opensearch-provider-title = Dodaj OpenSearch pružatelja usluge +add-opensearch-provider-text = Unesite URL OpenSearch pružatelja usluge kako biste dodali. Koristite direktni URL OpenSearch datoteke opisa ili URL gdje se može automatski otkriti. +adding-opensearch-provider-failed-title = Dodavanje OpenSearch pružatelja usluge nije uspjelo +adding-opensearch-provider-failed-text = Nije moguće dodati OpenSearch pružatelja usluge za { $url }. minimize-to-tray-label = .label = Kada je { -brand-short-name } smanjen, premjesti ga u sistemsku traku .accesskey = m - new-message-arrival = Kada stigne nova poruka: mail-play-sound-label = .label = @@ -191,30 +144,24 @@ mail-play-button = .label = Reproduciraj .accesskey = c - change-dock-icon = Promjeni postavke za aplikacijsku ikonu app-icon-options = .label = Mogućnosti aplikacijske ikone… .accesskey = n - notification-settings = Obavijesti i zadani zvukovi se mogu isključiti u okviru obavijesti u postavkama sustava. - +notification-settings2 = Obavijesti i zadani zvukovi se mogu isključiti u okviru obavijesti u postavkama sustava. animated-alert-label = .label = Prikaži obavijest .accesskey = P customize-alert-label = .label = Prilagodi… .accesskey = a - biff-use-system-alert = .label = Koristi obavijesti sustava - tray-icon-unread-label = .label = Prikaži ikonu za nepročitane poruke u sistemskoj traci .accesskey = t - tray-icon-unread-description = Preporučeno prilikom upotrebe malih tipki na programskoj traci - mail-system-sound-label = .label = Standardni zvuk sustava za novu poštu .accesskey = S @@ -224,27 +171,21 @@ mail-browse-sound-button = .label = Odaberi… .accesskey = b - enable-gloda-search-label = .label = Omogući globalno pretraživanje i indeksiranje .accesskey = e - datetime-formatting-legend = Oblikovanje datuma i vremena language-selector-legend = Jezik - allow-hw-accel = .label = Koristi hardversku akceleraciju kad je moguće .accesskey = h - store-type-label = .value = Tip pohrane poruka za nove račune: .accesskey = T - mbox-store-label = .label = Datoteka po mapi (mbox) maildir-store-label = .label = Datoteka po poruci (maildir) - scrolling-legend = Klizanje autoscroll-label = .label = Koristi automatsko klizanje @@ -252,7 +193,6 @@ smooth-scrolling-label = .label = Koristi glatko klizanje .accesskey = g - system-integration-legend = Sistemska integracija always-check-default = .label = Prilikom pokretanja uvijek provjeri je li { -brand-short-name } zadani program za e-poštu @@ -260,7 +200,6 @@ check-default-button = .label = Provjeri sada… .accesskey = P - # Note: This is the search engine name for all the different platforms. # Platforms that don't support it should be left blank. search-engine-name = @@ -269,26 +208,20 @@ [windows] Windows pretraživanje *[other] { "" } } - search-integration-label = .label = Dopusti da { search-engine-name } pretražuje poruke .accesskey = D - config-editor-button = .label = Uređivač postavki… .accesskey = U - return-receipts-description = Odredite kako će { -brand-short-name } rukovati s potvrdama čitanja return-receipts-button = .label = Potvrde čitanja… .accesskey = r - update-app-legend = { -brand-short-name } ažuriranja - # Variables: # $version (String): version of Thunderbird, e.g. 68.0.1 update-app-version = Inačica { $version } - allow-description = Dozvoli { -brand-short-name } da automatic-updates-label = .label = Automatski instaliraj dopune (preporučeno: poboljšana sigurnost) @@ -296,40 +229,30 @@ check-updates-label = .label = Provjeri dostupnost dopuna, ali mi ponudi želim li ih instalirati .accesskey = d - update-history-button = .label = Prikaži povijest ažuriranja .accesskey = P - use-service = .label = Koristi pozadinski proces za instalaciju nadogradnji .accesskey = K - cross-user-udpate-warning = Ove postavke će se primijeniti na sve Windows račune i { -brand-short-name } profile koji koriste ovu { -brand-short-name } instalaciju. - networking-legend = Veza proxy-config-description = Podesite način na koji se{ -brand-short-name } povezuje na Internet - network-settings-button = .label = Postavke… .accesskey = s - offline-legend = Izvanmrežno offline-settings = Podesi izvanmrežne postavke - offline-settings-button = .label = Izvanmrežno… .accesskey = I - diskspace-legend = Diskovni prostor offline-compact-folder = .label = Sažmi sve mape kada će uštedjeti više od .accesskey = a - offline-compact-folder-automatically = .label = Pitaj svaki put prije sažimanja .accesskey = m - compact-folder-size = .value = MB ukupno @@ -340,7 +263,6 @@ use-cache-before = .value = Koristi do .accesskey = K - use-cache-after = MB prostora za priručnu memoriju ## @@ -348,42 +270,31 @@ smart-cache-label = .label = Premosti automatsko upravljanje priručnom memorijom .accesskey = v - clear-cache-button = .label = Očisti sada .accesskey = O - fonts-legend = Fontovi i boje - default-font-label = .value = Zadani font: .accesskey = d - default-size-label = .value = Veličina: .accesskey = l - font-options-button = .label = Napredno… .accesskey = N - color-options-button = .label = Boje… .accesskey = B - display-width-legend = Poruke s običnim tekstom - # Note : convert-emoticons-label 'Emoticons' are also known as 'Smileys', e.g. :-) convert-emoticons-label = .label = Grafički prikaži smješke .accesskey = r - display-text-label = Kod prikaza citiranih poruka s običnim tekstom: - style-label = .value = Stil: .accesskey = i - regular-style-item = .label = Normalno bold-style-item = @@ -392,37 +303,25 @@ .label = Kurziv bold-italic-style-item = .label = Podebljani kurziv - size-label = .value = Veličina: .accesskey = V - regular-size-item = .label = Normalno bigger-size-item = .label = Veće smaller-size-item = .label = Manje - quoted-text-color = .label = Boja: .accesskey = B - search-handler-table = .placeholder = Filtriraj vrste sadržaja i radnje - -type-column-label = - .label = Vrsta sadržaja - .accesskey = t - -action-column-label = - .label = Radnja - .accesskey = a - +type-column-header = Vrsta sadržaja +action-column-header = Radnja save-to-label = .label = Spremi datoteke u .accesskey = S - choose-folder-label = .label = { PLATFORM() -> @@ -434,30 +333,22 @@ [macos] i *[other] i } - always-ask-label = .label = Uvijek me pitaj gdje spremiti datoteke .accesskey = U - - display-tags-text = Oznake se mogu koristiti za kategoriziranje i određivanje prioriteta vaših poruka. - new-tag-button = .label = Nova… .accesskey = N - edit-tag-button = .label = Uredi… .accesskey = e - delete-tag-button = .label = Obriši .accesskey = O - auto-mark-as-read = .label = Automatski označi poruku kao pročitanu .accesskey = A - mark-read-no-delay = .label = Odmah pri prikazu .accesskey = O @@ -468,33 +359,26 @@ mark-read-delay = .label = Nakon prikazivanja u trajanju od .accesskey = d - seconds-label = sekundi ## open-msg-label = .value = Otvori poruke u: - open-msg-tab = .label = Novoj kartici .accesskey = t - open-msg-window = .label = Novom prozoru poruke .accesskey = N - open-msg-ex-window = .label = Postojećem prozoru poruke .accesskey = e - close-move-delete = .label = Zatvori prozor/karticu poruke prilikom premještanja ili brisanja .accesskey = Z - display-name-label = .value = Ime za prikaz: - condensed-addresses-label = .label = Prikaži samo ime za prikaz osoba iz mojeg adresara .accesskey = P @@ -504,13 +388,10 @@ forward-label = .value = Proslijedi poruke: .accesskey = P - inline-label = .label = Ugrađeno - as-attachment-label = .label = Kao privitak - extension-label = .label = dodaj nastavak nazivu datoteke .accesskey = e @@ -521,7 +402,6 @@ auto-save-label = .label = Automatski spremi svakih .accesskey = A - auto-save-end = minuta ## @@ -529,248 +409,182 @@ warn-on-send-accel-key = .label = Zatraži potvrdu kod slanja poruke pomoću tipkovničke kratice .accesskey = o - spellcheck-label = .label = Provjeri pravopis prije slanja .accesskey = P - spellcheck-inline-label = .label = Omogući provjeru pravopisa prilikom pisanja .accesskey = e - language-popup-label = .value = Jezik: .accesskey = J - download-dictionaries-link = Preuzmi više rječnika - font-label = .value = Font: .accesskey = F - font-size-label = .value = Veličina: .accesskey = V - default-colors-label = .label = Koristi zadane boje čitatelja .accesskey = d - font-color-label = .value = Boja teksta: .accesskey = t - bg-color-label = .value = Boja pozadine: .accesskey = B - restore-html-label = .label = Vrati zadane postavke .accesskey = r - default-format-label = .label = Koristi kao zadano oblik odlomka umjesto teksta tijela .accesskey = o - format-description = Podesite ponašanje prilikom oblikovanja teksta - send-options-label = .label = Mogućnosti slanja… .accesskey = s - autocomplete-description = Kod adresiranja poruka, traži odgovarajuće adrese u: - ab-label = .label = Lokalnom adresaru .accesskey = L - directories-label = .label = Poslužiteljskom imeniku: .accesskey = P - directories-none-label = .none = Nepostojeći - edit-directories-label = .label = Uredi imenike… .accesskey = e - email-picker-label = .label = Automatski dodaj adrese e-pošte iz poslanih poruka u moj: .accesskey = A - default-directory-label = .value = Zadana početna mapa u prozoru adresara: .accesskey = s - default-last-label = .none = Zadnje korištena mapa - attachment-label = .label = Provjeravaj nedostaju li privici .accesskey = n - attachment-options-label = .label = Ključne riječi… .accesskey = K - enable-cloud-share = .label = Ponuda za razmjenu datoteka većih od cloud-share-size = .value = MB - add-cloud-account = .label = Dodaj… .accesskey = a .defaultlabel = Dodaj… - remove-cloud-account = .label = Ukloni .accesskey = U - find-cloud-providers = .value = Pronađite više davatelja usluga… - cloud-account-description = Dodaj novu Filelink uslugu pohrane ## Privacy Tab mail-content = Sadržaj poruke - remote-content-label = .label = Dozvoli vanjski sadržaj u porukama .accesskey = a - exceptions-button = .label = Izuzeci… .accesskey = I - remote-content-info = .value = Saznajte više o problemima oko privatnosti kod vanjskog sadržaja - web-content = Web sadržaj - history-label = .label = Zapamti web stranice i poveznice koje sam posjetio .accesskey = r - cookies-label = .label = Prihvati kolačiće od stranica .accesskey = r - third-party-label = .value = Prihvati kolačiće trećih strana: .accesskey = h - third-party-always = .label = Uvijek third-party-never = .label = Nikada third-party-visited = .label = Od posjećenih - keep-label = .value = Zadrži do: .accesskey = Z - keep-expire = - .label = iteka roka + .label = isteka roka keep-close = .label = zatvaranja { -brand-short-name }-a keep-ask = .label = pitaj me svaki puta - cookies-button = .label = Prikaži kolačiće… .accesskey = k - do-not-track-label = .label = Šalji “Ne prati me” signal web stranicama (stranice ga ne moraju poštivati) .accesskey = N - learn-button = .label = Saznajte više - passwords-description = { -brand-short-name } može zapamtiti lozinke za sve vaše račune. - passwords-button = .label = Spremljene lozinke… .accesskey = S - primary-password-description = Glavna lozinka štiti sve vaše lozinke, ali se mora unijeti jednom za svaku prijavu. - primary-password-label = .label = Koristi glavnu lozinku .accesskey = u - primary-password-button = .label = Promijeni glavnu lozinku… .accesskey = m - forms-primary-pw-fips-title = Trenutačno ste u FIPS načinu rada. FIPS ne dopušta praznu glavnu lozinku. forms-master-pw-fips-desc = Promjena lozinke nije uspjela - - junk-description = Postavite svoje zadane postavke neželjene pošte. Specifične postavke za pojedini račun se mogu podesiti u postavkama računa. - junk-label = .label = Kada označim poruke kao neželjenu poštu: .accesskey = K - junk-move-label = .label = Premjesti ih u mapu "Neželjena pošta" .accesskey = j - junk-delete-label = .label = Obriši ih .accesskey = O - junk-read-label = .label = Poruke za koje se utvrdi da su neželjena pošta označi kao pročitane .accesskey = u - junk-log-label = .label = Omogući prilagodljivi zapisnik filtera neželjene pošte .accesskey = m - junk-log-button = .label = Prikaži zapisnik .accesskey = P - reset-junk-button = .label = Vrati na početne postavke .accesskey = r - phishing-description = { -brand-short-name } može analizirati poruke e-pošte kako bi otkrio prijevaru, tražeći tehnike koje se često koriste da bi vas zavarali. - phishing-label = .label = Obavjesti me ako se sumnja da je poruka koju čitam prijevara .accesskey = O - antivirus-description = { -brand-short-name } može olakšati antivirusnim programima analizu primljenih poruka e-pošte na viruse prije nego se pohrane lokalno. - antivirus-label = .label = Dozvoli antivirusnim programima da izoliraju pojedine primljene poruke .accesskey = a - certificate-description = Kada poslužitelj zatraži moj osobni certifikat: - certificate-auto = .label = Automatski odaberi jedan .accesskey = A - certificate-ask = .label = Pitaj me svaki put .accesskey = a - ocsp-label = .label = Upitajte OCSP poslužitelje da biste potvrdili validnost certifikata .accesskey = U - certificate-button = .label = Upravljanje certifikatima… .accesskey = U - security-devices-button = .label = Sigurnosni uređaji… .accesskey = S @@ -780,10 +594,8 @@ startup-label = .value = Kada se { -brand-short-name } pokrene: .accesskey = s - offline-label = .label = Ostavi moj račun za razgovore odjavljenim - auto-connect-label = .label = Automatski spoji moje računa za razgovor @@ -796,7 +608,6 @@ idle-label = .label = Obavjesti moje kontakte da sam neaktivan nakon .accesskey = i - idle-time-label = minuta neaktivnosti ## @@ -804,24 +615,19 @@ away-message-label = .label = i postavi moj status na Odsutan s ovom porukom: .accesskey = a - send-typing-label = .label = Šalji obavjest o tipkanju u razgovorima .accesskey = t - notification-label = Kada stignu poruke naslovljene na vas: - show-notification-label = .label = Prikaži obavijest: .accesskey = k - notification-all = .label = s imenom pošiljatelja i pregledom poruke notification-name = .label = samo s imenom pošiljatelja notification-empty = .label = bez bilo kakvih informacija - notification-type-label = .label = { PLATFORM() -> @@ -833,31 +639,24 @@ [macos] A *[other] B } - chat-play-sound-label = .label = Reproduciraj zvuk .accesskey = d - chat-play-button = .label = Reproduciraj .accesskey = p - chat-system-sound-label = .label = Zadani sistemski zvuk za novu poruku .accesskey = Z - chat-custom-sound-label = .label = Koristi sljedeću zvučnu datoteku .accesskey = u - chat-browse-sound-button = .label = Odaberi… .accesskey = d - theme-label = .value = Motiv: .accesskey = T - style-thunderbird = .label = Thunderbird style-bubbles = @@ -868,15 +667,12 @@ .label = Papirnati listovi style-simple = .label = Jednostavno - preview-label = Pregled: no-preview-label = Nema dostupnog pregleda no-preview-description = Ovaj motiv je neispravan ili trenutačno nedostupan (isključen dodatak, siguran način rada, …). - chat-variant-label = .value = Varijanta: .accesskey = V - # This is used to determine the width of the search field in about:preferences, # in order to make the entire placeholder string visible # @@ -891,13 +687,31 @@ ## Preferences UI Search Results -search-results-header = Rezultati pretrage +# This is used to determine the width of the search field in about:preferences, +# in order to make the entire placeholder string visible +# +# Please keep the placeholder string short to avoid truncation. +# +# Notice: The value of the `.style` attribute is a CSS string, and the `width` +# is the name of the CSS property. It is intended only to adjust the element's width. +# Do not translate. +search-preferences-input2 = + .style = width: 15.4em + .placeholder = Pronađi u postavkama + +## Settings UI Search Results +search-results-header = Rezultati pretrage # `` will be replaced by the search term. search-results-empty-message = { PLATFORM() -> [windows] Žao nam je! U mogućnostima nema rezultata za „”. *[other] Žao nam je! U postavkama nema rezultata za „”. } - +# `` will be replaced by the search term. +search-results-empty-message2 = + { PLATFORM() -> + [windows] Oprosti! Među postavkama nema rezultata za “”. + *[other] Oprosti! Među postavkama nema rezultata za “”. + } search-results-help-link = Trebaš pomoć? Posjeti { -brand-short-name } podršku diff -Nru thunderbird-91.7.0+build2/l10n/hr/netwerk/necko.properties thunderbird-91.8.1+build1/l10n/hr/netwerk/necko.properties --- thunderbird-91.7.0+build2/l10n/hr/netwerk/necko.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/netwerk/necko.properties 2022-04-15 07:53:35.000000000 +0000 @@ -2,20 +2,14 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ResolvingHost=Looking up -#ConnectedTo=Connected to -#ConnectingTo=Connecting to -#SendingRequestTo=Sending request to -#TransferringDataFrom=Transferring data from - -3=Provjera %1$S... -4=Spojen na %1$S... -5=Slanje zahtjeva na %1$S... -6=Prijenos podataka iz %1$S... -7=Povezivanje na %1$S... +3=Provjerava se %1$S … +4=Spojeno na %1$S … +5=Slanje zahtjeva na %1$S … +6=Prijenos podataka iz %1$S … +7=Povezivanje na %1$S … 8=Pročitano %1$S\u0020 9=Zapisano %1$S -10=Čekanje na %1$S... +10=Čekanje na %1$S … 11=Provjeren %1$S… 12=Izvršavanje TLS provjere s %1$S… 13=Završena TLS provjera s %1$S… @@ -36,15 +30,11 @@ TrackerUriBlocked=Resurs na „%1$S” je blokiran, jer je blokiranje sadržaja aktivirano. UnsafeUriBlocked=Izvor je na “%1$S” blokiran značajkom Sigurno pretraživanje. +# LOCALIZATION NOTE (CORPBlocked): %1$S is the URL of the blocked resource. %2$S is the URL of the MDN page about CORP. CookieBlockedByPermission=Zahtjev za pristup kolačićima ili spremištu na „”%1$S” je blokiran zbog prilagođenih dozvola za kolačiće. CookieBlockedTracker=Zahtjev za pristup kolačiću ili spremištu na „%1$S” je blokiran, jer ga je poslao programa za praćenje a blokiranje sadržaja je aktivirano. CookieBlockedAll=Zahtjev za pristup kolačićima ili spremištu na „%1$S” je blokiran , jer blokiramo sve zahtjeve za pristup spremištu. CookieBlockedForeign=Zahtjev za pristup kolačićima ili spremištu na „%1$S” je blokiran, jer blokiramo sve zahtjeve trećih strana za pristup spremištu a blokiranje sadržaja je aktivirano. - -# As part of dynamic first-party isolation, third-party resources might be limited to "partitioned" storage access that is separate from the first-party context. -# This allows e.g. cookies to still be set, and prevents tracking without totally blocking storage access. This message is shown in the web console when this happens -# to inform developers that their storage is isolated. - # As part of dynamic state partitioning, third-party resources might be limited to "partitioned" storage access that is separate from the first-party context. # This allows e.g. cookies to still be set, and prevents tracking without totally blocking storage access. This message is shown in the web console when this happens # to inform developers that their storage is isolated. @@ -78,3 +68,5 @@ # LOCALIZATION NOTE (CookieRejectedNonsecureOverSecure): %1$S is the cookie name. # LOCALIZATION NOTE (CookieRejectedExpired): %1$S is the cookie name. # LOCALIZATION NOTE (CookieRejectedForNonSameSiteness): %1$S is the cookie name. + +# LOCALIZATION NOTE (APIDeprecationWarning): %1$S is the deprecated API; %2$S is the API function that should be used. diff -Nru thunderbird-91.7.0+build2/l10n/hr/security/manager/security/certificates/certManager.ftl thunderbird-91.8.1+build1/l10n/hr/security/manager/security/certificates/certManager.ftl --- thunderbird-91.7.0+build2/l10n/hr/security/manager/security/certificates/certManager.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/security/manager/security/certificates/certManager.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,126 +4,90 @@ certmgr-title = .title = Upravljač certifikata - certmgr-tab-mine = .label = Tvoji certifikati - certmgr-tab-people = .label = Osobe - certmgr-tab-servers = .label = Poslužitelji - certmgr-tab-ca = .label = Certifikacijska tijela - certmgr-mine = Imaš certifikate sljedećih organizacija koje te identificiraju certmgr-people = Imaš spremljene certifikate koji identificiraju sljedeće osobe certmgr-ca = Imaš spremljene certifikate koji identificiraju ova certifikacijska tijela - certmgr-edit-ca-cert = .title = Uredi postavke povjerenja CA-ovih certifikata .style = width: 48em; - certmgr-edit-cert-edit-trust = Uredi postavke povjerenja: - certmgr-edit-cert-trust-ssl = .label = Ovaj certifikat može identificirati web stranice. - certmgr-edit-cert-trust-email = .label = Ovaj certifikat može identificirati korisnike e-pošte. - certmgr-delete-cert = .title = Izbriši certifikat .style = width: 48em; height: 24em; - certmgr-cert-host = .label = Poslužitelj - certmgr-cert-name = .label = Naziv certifikata - certmgr-cert-server = .label = Poslužitelj - certmgr-override-lifetime = .label = Vijek trajanja - certmgr-token-name = .label = Sigurnosni uređaj - certmgr-begins-label = .label = Počinje na - certmgr-expires-label = .label = Isteći će - certmgr-email = .label = Adresa e-pošte - certmgr-serial = .label = Serijski broj - certmgr-view = .label = Pogled… .accesskey = P - certmgr-edit = .label = Uredi povjerenje… .accesskey = U - certmgr-export = - .label = Izvoz… + .label = Izvezi … .accesskey = z - certmgr-delete = .label = Izbriši … .accesskey = b - certmgr-delete-builtin = .label = Izbriši ili ne vjeruj … .accesskey = I - certmgr-backup = .label = Izradi sigurnosnu kopiju … .accesskey = s - certmgr-backup-all = .label = Izradi sigurnosnu kopiju za sve … .accesskey = k - certmgr-restore = - .label = Uvezi… + .label = Uvezi … .accesskey = v - certmgr-add-exception = .label = Dodaj iznimku… .accesskey = D - exception-mgr = .title = Dodaj sigurnosnu iznimku - exception-mgr-extra-button = .label = Potvrdi sigurnosnu iznimku .accesskey = r - exception-mgr-supplemental-warning = Legitimne banke, trgovine i ostale javne stranice te neće tražiti da ovo učiniš. - exception-mgr-cert-location-url = .value = Lokacija: - exception-mgr-cert-location-download = .label = Preuzmi certifikat .accesskey = c - exception-mgr-cert-status-view-cert = .label = Pogled… .accesskey = P - exception-mgr-permanent = .label = Trajno spremi ovu iznimku .accesskey = i - pk11-bad-password = Lozinka koju ste upisali je bila netočna. pkcs12-decode-err = Dekodiranje datoteke nije uspjelo. Ili datoteka nije u PKCS #12 formatu ili je oštećena ili je lozinka koju ste unijeli bila kriva. pkcs12-unknown-err-restore = Vraćanje PKCS #12 datoteke nije uspjelo zbog nepoznatih razloga. @@ -156,30 +120,21 @@ .title = Izbriši svoje certifikate delete-user-cert-confirm = Stvarno želiš izbrisati ove certifikate? delete-user-cert-impact = Ako izbrišeš jedan od vlastitih certifikata, više ga nećeš moći koristiti za identifikaciju. - - delete-ssl-override-confirm = Sigurno izbrisati ovu iznimku poslužitelja? - delete-ca-cert-title = .title = Brisanje ili poništavanje povjerenja CA certifikata delete-ca-cert-confirm = Zatražio/la si brisanje ovih CA certifikata. Za ugrađene certifikate uklonit će se sva povjerenja, što ima isti efekt. Zaista želiš izbrisati certifikate ili poništiti povjerenje? delete-ca-cert-impact = Ako izbrišeš ili poništiš povjerenje za certifikat certifikacijskog tijela, ovaj program više neće vjerovati certifikatima koje izdaje to certifikacijsko tijelo. - - delete-email-cert-title = .title = Izbriši certifikate e-pošte delete-email-cert-confirm = Stvarno želiš izbrisati certifikate e-pošte ovih ljudi? delete-email-cert-impact = Ako izbrišete certifikat e-pošte određene osobe, više nećeš moći toj osobi slati šifrirane e-poruke. - # Used for semi-uniquely representing a cert. # # Variables: # $serialNumber : the serial number of the cert in AA:BB:CC hex format. cert-with-serial = .value = Certifikat sa serijskim brojem: { $serialNumber } - -## Cert Viewer - # Used when no cert is stored for an override no-cert-stored-for-override = (nije pohranjeno) diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/global/aboutStudies.properties thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/global/aboutStudies.properties --- thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/global/aboutStudies.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/global/aboutStudies.properties 2022-04-15 07:53:35.000000000 +0000 @@ -17,8 +17,8 @@ # LOCALIZATION NOTE (completeStatus): Displayed for a study that is already complete completeStatus = Završeno -updateButtonWin = Ažuriraj postavke -updateButtonUnix = Postavke aktualiziranja +updateButtonWin = Aktualiziraj opcije +updateButtonUnix = Aktualiziraj postavke learnMore = Saznaj više noStudies = Niste sudjelovali u niti jednoj studiji. disabledList = Ovo je popis studija u kojima ste sudjelovali. Nove studije se neće pokretati. diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.dtd thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.dtd --- thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.dtd 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.dtd 2022-04-15 07:53:35.000000000 +0000 @@ -8,7 +8,7 @@ - + @@ -18,7 +18,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.properties thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.properties --- thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/mozapps/downloads/unknownContentType.properties 2022-04-15 07:53:35.000000000 +0000 @@ -4,7 +4,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. title=Otvaranje %S -saveDialogTitle=Upišite naziv datoteke za spremanje u... +saveDialogTitle=Upiši ime datoteke za spremanje u … defaultApp=%S (standardno) chooseAppFilePickerTitle=Odaberi pomoćnu aplikaciju badApp=Odabrani program ("%S") nije pronađen. Provjeri naziv datoteke ili odaberi jedan drugi program. diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/mozapps/update/updates.properties thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/mozapps/update/updates.properties --- thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/mozapps/update/updates.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/mozapps/update/updates.properties 2022-04-15 07:53:35.000000000 +0000 @@ -9,8 +9,6 @@ noThanksButton=Ne hvala noThanksButton.accesskey=N -# NOTE: The restartLaterButton string is also used in -# mozapps/extensions/content/blocklist.js restartLaterButton=Ponovo pokreni kasnije restartLaterButton.accesskey=K restartNowButton=Ponovo pokreni %S @@ -32,7 +30,7 @@ check_error-2152398862=Isteklo vrijeme veze # NS_ERROR_OFFLINE check_error-2152398864=Mreža nije dostupna (povežite se) -check_error-2152398867=Ulaz nije dozvoljen +check_error-2152398867=Priključak nije dozvoljen check_error-2152398868=Podaci nisu primljeni (pokušaj ponovo) check_error-2152398878=Poslužitelj za aktualiziranje nije pronađen (provjeri vezu s internetom) check_error-2152398890=Proxy poslužitelj nije pronađen (check your internet connection) @@ -42,4 +40,4 @@ check_error-2152398920=Proxy poslužitelj odbio povezivanje check_error-2153390069=Certifikat poslužitelja je istekao (podesi vrijeme i datum na svom sustavu, ako je pogrešno) check_error-verification_failed=Integritet ove dopune ne može biti potvrđen -check_error-move_failed=Priprema ažuriranja za instalaciju nije uspjela +check_error-move_failed=Priprema aktualiziranja instalacije nije uspjela diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/passwordmgr/passwordmgr.properties thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/passwordmgr/passwordmgr.properties --- thunderbird-91.7.0+build2/l10n/hr/toolkit/chrome/passwordmgr/passwordmgr.properties 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/chrome/passwordmgr/passwordmgr.properties 2022-04-15 07:53:35.000000000 +0000 @@ -16,8 +16,8 @@ saveLoginButtonNever.accesskey = e # LOCALIZATION NOTE (updateLoginMsg3, updateLoginMsgNoUser3): # %S is the login's hostname. -updateLoginMsg3 = Ažurirati prijavu za %S? -updateLoginMsgNoUser3 = Ažurirati lozinku za %S? +updateLoginMsg3 = Aktualizirati prijavu za %S? +updateLoginMsgNoUser3 = Aktualizirati lozinku za %S? updateLoginMsgAddUsername2 = Dodati korisničko ime spremljenoj lozinki? updateLoginButtonText = Dopuna updateLoginButtonAccessKey = V diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/aboutAddons.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/aboutAddons.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/aboutAddons.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/aboutAddons.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -100,7 +100,7 @@ disabled-unsigned-heading = .value = Neki dodaci su isključeni disabled-unsigned-description = Navedeni dodaci nisu mogli biti verificirani za korištenje u { -brand-short-name }u. Možete ili kontaktirati autora dodataka da zatraži njihovu verifikaciju. -disabled-unsigned-learn-more = Saznaj više o našim naporima da te zaštitimo na Internetu. +disabled-unsigned-learn-more = Saznaj više o našim naporima da te zaštitimo na internetu. disabled-unsigned-devinfo = Programeri koji su zainteresirani za verifikaciju svojih dodataka, mogu nastaviti čitati naš . plugin-deprecation-description = Ne možeš pronaći priključak koji tražiš? Neke priključke { -brand-short-name } više ne podržava. legacy-warning-show-legacy = Prikaži zastarjele dodatke @@ -301,8 +301,8 @@ addon-detail-homepage-label = Početna stranica addon-detail-rating-label = Ocjena # Message for add-ons with a staged pending update. -install-postponed-message = Ovo proširenje bit će ažurirano kad se { -brand-short-name } ponovno pokrene. -install-postponed-button = Ažuriraj sada +install-postponed-message = Ovo proširenje će se aktualizirati kad se { -brand-short-name } ponovno pokrene. +install-postponed-button = Aktualiziraj sada # The average rating that the add-on has received. # Variables: # $rating (number) - A number between 0 and 5. The translation should show at most one digit after the comma. diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/aboutNetworking.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/aboutNetworking.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/aboutNetworking.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/aboutNetworking.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -13,7 +13,7 @@ about-networking-refresh = Osvježi about-networking-auto-refresh = Automatski osviježi svake 3 sekunde about-networking-hostname = Adresa poslužitelja -about-networking-port = Ulaz +about-networking-port = Priključak about-networking-http-version = HTTP verzija about-networking-ssl = SSL about-networking-active = Aktivno diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/abuseReports.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/abuseReports.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/abuseReports.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/abuseReports.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -8,19 +8,15 @@ # Variables: # $addon-name (string) - Name of the add-on being reported abuse-report-dialog-title = Prijava za { $addon-name } - abuse-report-title-extension = Prijavi ovaj dodatak prodavaču { -vendor-short-name } abuse-report-title-theme = Prijavi ovu temu prodavaču { -vendor-short-name } abuse-report-subtitle = Što je problem? - # Variables: # $author-name (string) - Name of the add-on author abuse-report-addon-authored-by = od { $author-name } - abuse-report-learnmore = Ne znaš koji problem odabrati? Saznaj više o prijavljivanju problema s dodacima i temama - abuse-report-submit-description = Opišite problem (opcionalno) abuse-report-textarea = .placeholder = Lakše nam je ispraviti pogrešku ukoliko znamo detalje problema. Opiši događaj. Hvala, što nam pomažeš održati web zdravim. @@ -36,13 +32,6 @@ abuse-report-submit-button = Pošalji ## Message bars descriptions. - - -## Variables: -## $addon-name (string) - Name of the add-on - - -## Message bars descriptions. ## ## Variables: ## $addon-name (string) - Name of the add-on @@ -60,6 +49,8 @@ abuse-report-messagebar-action-remove-extension = Da, ukloni abuse-report-messagebar-action-keep-extension = Ne, zadržat ću +abuse-report-messagebar-action-remove-sitepermission = Da, ukloni +abuse-report-messagebar-action-keep-sitepermission = Ne, zadržat ću abuse-report-messagebar-action-remove-theme = Da, ukloni abuse-report-messagebar-action-keep-theme = Ne, zadržat ću abuse-report-messagebar-action-retry = Pokušaj ponovo @@ -69,19 +60,16 @@ abuse-report-damage-reason-v2 = Oštetilo je moje računalo ili ugrozilo moje podatke abuse-report-damage-example = Primjer: Ubrizgani zlonamjerni program ili ukradeni podaci - abuse-report-spam-reason-v2 = Sadrži neželjeni sadržaj ili ubacuje nepoželjne oglase abuse-report-spam-example = Primjer: Umeće reklame na web stranice - abuse-report-settings-reason-v2 = Promijenilo je moju tražilicu, početnu stranicu ili novu karticu bez obavještavanja ili traženja dopuštenja abuse-report-settings-suggestions = Prije prijave dodatka, možete pokušati izmijeniti svoje postavke: abuse-report-settings-suggestions-search = Promijeni svoje standardne postavke za pretraživanje abuse-report-settings-suggestions-homepage = Izmijenite svoju početnu stranicu ili novu karticu - abuse-report-deceptive-reason-v2 = Tvrdi da je nešto što nije abuse-report-deceptive-example = Primjer: Obmanjujući opis ili slike - abuse-report-broken-reason-extension-v2 = Ne radi, slama web-stranice ili usporava { -brand-product-name } +abuse-report-broken-reason-sitepermission-v2 = Ne radi, ne prikazuje web-stranice ispravno ili usporava { -brand-product-name } abuse-report-broken-reason-theme-v2 = Ne radi ili slama prikaz preglednika abuse-report-broken-example = Primjer: Funkcije su spore, teško ih je koristiti ili ne rade, dijelovi web stranica se ne mogu učitati ili čudno izgledaju abuse-report-broken-suggestions-extension = @@ -92,14 +80,10 @@ Čini se da se radi o grešci. Pored slanja prijave ovdje, najbolji način za rješavanje funkcionalnih problema je da kontaktiraš programera teme. Podatke o programeru potraži na web-stranici dodatka. - abuse-report-policy-reason-v2 = Sadrži mržnju, nasilan ili ilegalan sadržaj abuse-report-policy-suggestions = Napomena: Problemi s autorskim pravima i zaštitnim znakovima moraju se prijaviti u odvojenom procesu. Koristite ova upute za prijavu problema. - abuse-report-unwanted-reason-v2 = Nisam to želio i ne znam kako to ukloniti abuse-report-unwanted-example = Primjer: Aplikacija instalirana bez mog dopuštenja - abuse-report-other-reason = Nešto drugo - diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/certviewer.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/certviewer.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/about/certviewer.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/about/certviewer.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -81,7 +81,6 @@ certificate-viewer-certificate-policies = Pravila certifikata certificate-viewer-embedded-scts = Ugrađeni SCT-ovi certificate-viewer-crl-endpoints = Krajnje točke CRL-a - # This message is used as a row header in the Miscellaneous section. # The associated data cell contains links to download the certificate. certificate-viewer-download = Preuzmi @@ -101,11 +100,10 @@ .download = { $fileName }.pem certificate-viewer-download-pem-chain = PEM (lanac) .download = { $fileName }-chain.pem - # The title attribute for Critical Extension icon certificate-viewer-critical-extension = .title = Ovaj dodatak je označen kao kritičan, što znači da klijenti moraju odbaciti certifikat ukoliko ga ne razumiju. -certificate-viewer-export = Izvoz +certificate-viewer-export = Izvezi .download = { $fileName }.pem ## diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/global/createProfileWizard.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/global/createProfileWizard.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/global/createProfileWizard.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/global/createProfileWizard.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -13,13 +13,9 @@ [macos] Uvod *[other] Dobrodošli u { create-profile-window.title } } - profile-creation-explanation-1 = { -brand-short-name } sprema informacije o tvojim postavkama i osobitostima u tvoj osobni profil. - profile-creation-explanation-2 = Ako ovu kopiju { -brand-short-name(case: "gen") } dijelite s ostalima, možete koristiti profile kako biste informacije svakog korisnika držali odvojenima. Da biste to uradili, svaki korisnik bi trebao stvoriti svoj vlastiti profil. - profile-creation-explanation-3 = Ako si jedini korisnik ove verzije { -brand-short-name(case: "gen") }, moraš imati barem jedan profil. Ako želiš, možeš stvoriti više profila za spremanje različitih postavki i osobitosti. Na primjer, možeš imati odvojene profile za poslovnu i osobnu upotrebu. - profile-creation-explanation-4 = { PLATFORM() -> [macos] Za početak stvaranja tvog profila, klikni na Nastavi. @@ -33,21 +29,15 @@ [macos] Zaključak *[other] Dovršavanje { create-profile-window.title } } - profile-creation-intro = Ako stvoriš nekoliko profila, možeš ih razlikovati po njihovim imenima. Možeš koristiti imena koja su ovdje zadana ili stvoriti svoja vlastita. - profile-prompt = Upiši ime novog profila: .accesskey = e - profile-default-name = .value = Standardni korisnik - profile-directory-explanation = Tvoje korisničke postavke, osobitosti i ostali korisnički podaci bit će spremljeni u: - create-profile-choose-folder = - .label = Odaberi mapu... - .accesskey = m - + .label = Odaberi mapu … + .accesskey = O create-profile-use-default = .label = Koristi standardnu mapu .accesskey = u diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/global/profileSelection.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/global/profileSelection.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/global/profileSelection.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/global/profileSelection.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -9,14 +9,14 @@ profile-selection-button-cancel = .label = Izlaz profile-selection-new-button = - .label = Stvori profil... - .accesskey = p + .label = Stvori profil … + .accesskey = S profile-selection-rename-button = - .label = Preimenuj profil... - .accesskey = r + .label = Preimenuj profil … + .accesskey = P profile-selection-delete-button = - .label = Izbriši profil... - .accesskey = p + .label = Izbriši profil … + .accesskey = I profile-selection-conflict-message = Druga { -brand-product-name } kopija je napravila izmjene u profilu. Morate ponovo pokrenuti { -brand-short-name } prije nego li napravite nove izmjene. ## Messages used in the profile manager diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/global/unknownContentType.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/global/unknownContentType.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/global/unknownContentType.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/global/unknownContentType.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -20,11 +20,11 @@ .label = Otvori s .accesskey = O unknowncontenttype-other = - .label = Drugo... + .label = Drugo … unknowncontenttype-choose-handler = .label = { PLATFORM() -> - [macos] Odaberi... + [macos] Odaberi … *[other] Pregledaj … } .accesskey = diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/printing/printDialogs.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/printing/printDialogs.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/printing/printDialogs.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/printing/printDialogs.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -4,7 +4,7 @@ print-setup = .title = Postava stranice -custom-prompt-title = Prilagođeno... +custom-prompt-title = Prilagođeno … custom-prompt-prompt = Upiši tvoj standardni tekst zaglavlja/podnožja basic-tab = .label = Format i opcije @@ -90,20 +90,19 @@ hf-page-and-total = .label = Stranica # od # hf-custom = - .label = Prilagođeno... + .label = Prilagođeno … print-preview-window = .title = Pregled ispisa print-title = .value = Naslov: print-preparing = - .value = Priprema... + .value = Pripremanje … print-progress = .value = Napredak: print-window = .title = Ispisivanje print-complete = .value = Ispisivanje je dovršeno. - # Variables # $percent (integer) - Number of printed percentage print-percent = diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/printing/printPreview.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/printing/printPreview.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/printing/printPreview.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/printing/printPreview.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -25,7 +25,7 @@ printpreview-shrink-to-fit = .label = Smanji na veličinu prozora printpreview-custom = - .label = Prilagođeno... + .label = Prilagođeno … printpreview-print = .label = Ispiši … .accesskey = p @@ -33,12 +33,11 @@ .value = od printpreview-custom-scale-prompt-title = Prilagođen omjer printpreview-page-setup = - .label = Postavke stranice... + .label = Postavke stranice … .accesskey = s printpreview-page = .value = Stranica: .accesskey = a - # Variables # $sheetNum (integer) - The current sheet number # $sheetCount (integer) - The total number of sheets to print @@ -62,7 +61,6 @@ printpreview-endarrow = .label = { $arrow } .tooltiptext = Posljednja stranica - printpreview-homearrow-button = .title = Prva stranica printpreview-previousarrow-button = diff -Nru thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/printing/printUI.ftl thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/printing/printUI.ftl --- thunderbird-91.7.0+build2/l10n/hr/toolkit/toolkit/printing/printUI.ftl 2022-03-07 21:38:36.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hr/toolkit/toolkit/printing/printUI.ftl 2022-04-15 07:53:35.000000000 +0000 @@ -27,7 +27,7 @@ printui-copies-label = Kopije printui-orientation = Usmjerenje printui-landscape = Horizontalno -printui-portrait = Vertikalno +printui-portrait = Uspravno # Section title for the printer or destination device to target printui-destination-label = Odredište printui-destination-pdf-label = Spremi u PDF @@ -115,8 +115,8 @@ printui-paper-b4 = B4 printui-paper-jis-b5 = JIS-B5 printui-paper-jis-b4 = JIS-B4 -printui-paper-letter = Američko pismo -printui-paper-legal = Američki pravni +printui-paper-letter = US Letter +printui-paper-legal = US Legal printui-paper-tabloid = Tabloid ## Error messages shown when a user has an invalid input diff -Nru thunderbird-91.7.0+build2/l10n/hsb/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/hsb/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/hsb/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Priwatnosć: Priwatny podawk calendar-editable-item-privacy-icon-confidential = .alt = Priwatnosć: Jenož čas a datum pokazać +calendar-editable-item-recurrence = + .alt = Wospjetowanje +calendar-editable-item-recurrence-exception = + .alt = Wospjetowanske wuwzaće calendar-editable-item-todo-icon-task = .alt = Nadawk calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/hsb/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/hsb/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/hsb/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:53:43.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } je was přeprosył do: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Składować +calendar-invitation-panel-accept-button = Haj +calendar-invitation-panel-decline-button = Ně +calendar-invitation-panel-tentative-button = Snano +calendar-invitation-panel-reply-status = * Hišće njejsće rozsudźił abo wotmołwił +calendar-invitation-panel-prop-title-when = Hdy: +calendar-invitation-panel-prop-title-location = Městno: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Wobdźělnicy: +calendar-invitation-panel-prop-title-description = Wopisanje: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } haj + [DECLINED] { $count } ně + [TENTATIVE] { $count } snano + [NEEDS-ACTION] { $count } wustejacych + [TOTAL] { $count } wobdźělnikow + *[OTHER] { $count } druhich + } diff -Nru thunderbird-91.7.0+build2/l10n/hsb/chat/irc.properties thunderbird-91.8.1+build1/l10n/hsb/chat/irc.properties --- thunderbird-91.7.0+build2/l10n/hsb/chat/irc.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/chat/irc.properties 2022-04-15 07:53:42.000000000 +0000 @@ -172,7 +172,7 @@ error.sendMessageFailed=Při słanju wašeje poslednjeje powěsće je zmylk wustupił. Prošu spytajće hišće raz, hdyž zwisk je so wobnowił. # %1$S is the channel the user tried to join, %2$S is the channel # he was forwarded to. -error.channelForward=Snano nochceće so %1$S přidružić, a budźeće so awtomatisce do %2$S dale sposrědkować. +error.channelForward=Snano nochceće so %1$S přidružić, a budźeće so awtomatisce do %2$S hinak wodźić. # %S is the mode that the user tried to set but was not recognized # by the server as a valid mode. error.unknownMode='%S' płaćiwy wužiwarski modus na tutym serwerje njeje. diff -Nru thunderbird-91.7.0+build2/l10n/hsb/chat/matrix.properties thunderbird-91.8.1+build1/l10n/hsb/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/hsb/chat/matrix.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/chat/matrix.properties 2022-04-15 07:53:42.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S je wobkrućenje ze slědowaceje přičiny anulował: %2$S message.verification.done=Přepruwowanje je dokónčene. +message.decryptionError=Wobsah tuteje powěsće njeda so dešifrować. Zo byšće zaklučowanske kluče ze swojich druhich gratow požadał, klikńće z prawej tastu na powěsć. +message.decrypting=Dešifruje so… +message.redacted=Powěsć je so předźěłała. + +# Label in the message context menu +message.action.requestKey=Kluče znowa požadać +message.action.redact=Předźěłać +message.action.report=Powěsć zdźělić +message.action.retry=Znowa słać +message.action.cancel=Powěsć přetorhnyć + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Při słanju wašeje powěsće „%1$S“ je zmylk nastał. diff -Nru thunderbird-91.7.0+build2/l10n/hsb/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/hsb/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/hsb/devtools/client/aboutdebugging.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/devtools/client/aboutdebugging.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Pytanje zmylkow - konfiguracija - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Pytanje zmylkow - běžny čas / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Tutón { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Připrawjenje - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB zmóžnjeny - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB znjemóžnjeny - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Zwjazany # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Zwisk dźěleny - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = Žane graty namakane - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Zwjazać - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Zwjazuje so… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Zwisk je so nimokulił. - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = Zwisk je hišće wustejacy, přepruwujće za powěsćemi w cilowym wobhladowaku - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = Čas zwiska překročeny - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Čaka so na wobhladowak… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Dźěleny - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Pomoc za pytanje zmylkow - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Symbol pomocy - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Graty aktualizować @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Připrawjenje - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Konfigurujće zwiskowu metodu, z kotrejž chceće swój grat znazdala za zmylkami přepytować. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Wužiwajće { about-debugging-this-firefox-runtime-name }, zo byšće rozšěrjenja a service workers tuteje wersije { -brand-shorter-name } za zmylkami přepytował. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Z gratom zwjazać - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Hdyž so to zmóžnja, so trěbne komponenty za pytanje zmylkow USB Android sćehnu a so { -brand-shorter-name } přidadźa. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = USB-graty zmóžnić - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = USB-graty znjemóžnić - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Aktualizuje so… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Zmóžnjeny about-debugging-setup-usb-status-disabled = Znjemóžnjeny about-debugging-setup-usb-status-updating = Aktualizuje so… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Wuwiwarski meni na wašim graće Android zmóžnić. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Pytanje zmylkow USB we wuwiwarskim meniju Android zmóžnić. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Pytanje zmylkow USB w Firefox na graće Android zmóžnić. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Zwjazajće grat Android ze swojim ličakom. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Maće problemy při zwjazowanju z USB-gratom? Problem rozrisać - # Network section of the Setup page about-debugging-setup-network = .title = Syćowa adresa - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Maće problemy při zwjazowanju přez syćowu adresu? Problem rozrisać - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Přidać - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = Syćowe adresy hišće njejsu so přidali. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Host - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Wotstronić - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Njepłaćiwy "{ $host-value }": Wočakowany format je "hostowe mjeno:portowe čisło" - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Procesy - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Profilowy wukon - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Konfiguracija wašeho wobhladowaka ze service workers kompatibelna njeje. Dalše informacije - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = Zwjazany wobhladowak ma staru wersiju ({ $runtimeVersion }). Podpěrana minimalna wersija je ({ $minVersion }). To je njepodpěrana konfiguracija a móže zawinować, zo wuwiwarske nastroje njefunguja. Prošu aktualizujće zwjazany wobhladowak. Rozrisanje problemow - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = Tuta wersija Firefox njemóže Firefox za Android (68) za zmylkami přepruwować. Poručamy, zo Firefox za Android Nightly na swojim telefonje za testowanje instalujeće. Dalše podrobnosće - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = Zwjazany wobhladowak je aktualniši ({ $runtimeVersion }, buildID { $runtimeID }) hač waš { -brand-shorter-name } ({ $localVersion }, buildID { $localID }). To je njepodpěrana konfiguracija a móže zawinować, zo wuwiwarske nastroje njefunguja. Prošu aktualizujće Firefox. Rozrisanje problemow - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Zwisk dźělić - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Zwiskowu namołwu zmóžnić - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Zwiskowu namołwu znjemóžnić - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Profilowar - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Hišće ničo. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Přepytować - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Nachwilny přidatk začitać… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = Při instalowanju nachwilneho přidatka je zmylk nastał. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Znowa začitać - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Wotstronić - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Pozadkowy skript dokónčić # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Dataju manifest.json abo archiw .xpi/.zip wubrać - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Tute WebExtension ma nachwilny ID. Dalše informacije - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = URL manifesta - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = Nutřkowny UUID - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Městno - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = ID rozšěrjenja - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Pozadkowy skript +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Běži +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Zastajeny # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push .disabledTitle = Push service worker je tuchwilu znjemóžnjeny za multiprocesowy { -brand-shorter-name } - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Start .disabledTitle = Start service worker je tuchwilu znjemóžnjeny za multiprocesowy { -brand-shorter-name } - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Registrowanje zběhnyć - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Słuchanje na podawki Fetch - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = Žane słuchanje na podawki Fetch - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Běži - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Zastajeny - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Registruje so - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Wobwod - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Słužba Push - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = Přepruwowanje service worker je tuchwilu znjemóžnjene za multiprocesowy { -brand-shorter-name } - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = Rajtark njeje so dospołnje začitał a njeda so přepruwować - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Hłowny proces - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = Hłowny proces za cilowy wobhladowak - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Multiprocesowe graty - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Hłowny proces a wobsahowe procesy za cilowy wobhladowak - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Zdźělenku začinić - # Label text used for the error details of message component. about-debugging-message-details-label-error = Zmylkowe podrobnosće - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Warnowanske podrobnosće - # Label text used for default state of details of message component. about-debugging-message-details-label = Podrobnosće diff -Nru thunderbird-91.7.0+build2/l10n/hsb/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/hsb/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/hsb/devtools/client/compatibility.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/devtools/client/compatibility.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (eksperimentelny) compatibility-issue-prefixneeded = (prefiks trěbny) compatibility-issue-deprecated-experimental = (zestarjeny, eksperimentelny) - compatibility-issue-deprecated-prefixneeded = (zestarjeny, prefiks trěbny) compatibility-issue-experimental-prefixneeded = (eksperimentelny, prefiks trěbny) compatibility-issue-deprecated-experimental-prefixneeded = (zestarjeny, eksperimentelny, prefiks trěbny) @@ -45,7 +44,14 @@ [few] { $number } wustupowanja *[other] { $number } wustupowanjow } - compatibility-no-issues-found = Žane problemy kompatibelnosće namakane. compatibility-close-settings-button = .title = Nastajenja začinić +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Problemy kompatibelnosće w: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/hsb/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/hsb/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/hsb/devtools/client/netmonitor.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/devtools/client/netmonitor.properties 2022-04-15 07:53:42.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → callback %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=Znamješkowy rjećazk „%S“ je so ze spočatka JSON wotstronił, kotryž so deleka pokazuje + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Naprašowanski znamješkowy rjećazk: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL-parametry + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Hłowy naprašowanja: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Hłowy + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=mjeno + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=hódnota + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Wobsah + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=wužitna ćeža + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Wobsah naprašowanja: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Přetorhnyć +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Zhašeć + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Zapisk wotstronić + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Wróćo diff -Nru thunderbird-91.7.0+build2/l10n/hsb/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/hsb/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/hsb/devtools/client/toolbox-options.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/devtools/client/toolbox-options.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Zdalene pytanje za zmylkami options-enable-remote-tooltip2 = .title = Hdyž tute nastajenje zmóžnjeće, so instanca wobhladowaka znazdala za zmylkami přepytuje +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Swójske formatowaki zmóžnić +options-enable-custom-formatters-tooltip = + .title = Hdyž tute nastajenje zmóžnjeće, smědźa sydła swójske formatowaki za DOM-objekty definować # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Service worker přez HTTP zmóžnić (hdyž graty su wočinjene) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/hsb/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/hsb/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/hsb/devtools/client/webconsole.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/devtools/client/webconsole.properties 2022-04-15 07:53:42.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=Dataja +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Wšě powěsće kopěrować +webconsole.menu.copyAllMessages.accesskey=k + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Wšě powěsće do dataje składować +webconsole.menu.saveAllMessagesFile.accesskey=W + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/hsb/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/hsb/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/hsb/dom/chrome/dom/dom.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/dom/chrome/dom/dom.properties 2022-04-15 07:53:43.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Prošu zapodajće URL. FormValidationInvalidDate=Prošu zapodajće płaćiwy datum. FormValidationInvalidTime=Prošu zapodajće płaćiwy čas. +FormValidationInvalidDateTime=Prošu zapodajće płaćiwy datum a čas. +FormValidationInvalidDateMonth=Prošu zapodajće płaćiwy měsac. +FormValidationInvalidDateWeek=Prošu zapodajće płaćiwy tydźeń. FormValidationPatternMismatch=Prošu wužijće požadany format. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=Prošu wužijće požadany format: %S. diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/communicator/utilityOverlay.dtd thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/communicator/utilityOverlay.dtd --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/communicator/utilityOverlay.dtd 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/communicator/utilityOverlay.dtd 2022-04-15 07:53:42.000000000 +0000 @@ -23,7 +23,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/aboutDialog.dtd thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/aboutDialog.dtd --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/aboutDialog.dtd 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/aboutDialog.dtd 2022-04-15 07:53:42.000000000 +0000 @@ -61,7 +61,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/glodaFacetView.properties thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/glodaFacetView.properties --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/glodaFacetView.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/glodaFacetView.properties 2022-04-15 07:53:42.000000000 +0000 @@ -104,12 +104,12 @@ # LOCALIZATION NOTE (glodaFacetView.result.message.fromLabel): Used in the # faceted search message display to indicate the author of a message. # An example usage is "from: Bob". -glodaFacetView.result.message.fromLabel=wot: +glodaFacetView.result.message.fromLabel=wot: # LOCALIZATION NOTE (glodaFacetView.result.message.toLabel): Used in the # faceted search message display to indicate the recipients of a message. # An example usage is "to: Bob, Chuck, Don". -glodaFacetView.result.message.toLabel=do: +glodaFacetView.result.message.toLabel=do: # LOCALIZATION NOTE (glodaFacetView.result.message.noSubject): Used in the # faceted search message display to act as a click target for messages with diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:53:42.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/messenger.properties thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/messenger.properties --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/messenger.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/messenger.properties 2022-04-15 07:53:42.000000000 +0000 @@ -227,7 +227,7 @@ replied=Wotmołwjene forwarded=Dale sposrědkowane -redirected=Dalesposrědkowany +redirected=Hinak wodźeny new=Nowe read=Přečitane flagged=Z hwěžku diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/msgHdrViewOverlay.dtd thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/msgHdrViewOverlay.dtd --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/msgHdrViewOverlay.dtd 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/msgHdrViewOverlay.dtd 2022-04-15 07:53:42.000000000 +0000 @@ -29,7 +29,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/prefs.properties thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/prefs.properties --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/messenger/prefs.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/messenger/prefs.properties 2022-04-15 07:53:42.000000000 +0000 @@ -51,7 +51,7 @@ # account manager stuff prefPanel-server=Serwerowe nastajenja -prefPanel-copies=Kopije & rjadowaki +prefPanel-copies=Kopije a rjadowaki prefPanel-synchronization=Synchronizacija a składowanje prefPanel-diskspace=Tačelowy rum prefPanel-addressing=Pisać a adresować diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/overrides/netError.dtd thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/overrides/netError.dtd --- thunderbird-91.7.0+build2/l10n/hsb/mail/chrome/overrides/netError.dtd 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/chrome/overrides/netError.dtd 2022-04-15 07:53:42.000000000 +0000 @@ -61,7 +61,7 @@  
  • Přepruwujće proksynastajenja, zo byšće zawěsćił, zo su korektne.
  •  
  • Přepruwujće hač waš ličak ma fungowacy syćowy zwisk.
  •  
  • Jeli waš ličak abo waša syć so přez wohnjowu murju abo proksy škita, zawěsćće, zo &brandShortName; smě z webom zwjazać.
  •  "> - +  
  • Tutón problem so druhdy zawinuje, hdyž so placki znjemóžnjeja abo wotpokazuja.
  •  "> diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/aboutDialog.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Nowe funkcije a změny diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/aboutImport.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/aboutImport.ftl 2022-04-15 07:53:43.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Wubjerće, zwotkelž maja so konta, adresniki, protyki a druhe daty importować: import-address-book = Adresnikowu dataju importować import-calendar = Dataju protyki importować +export-profile = Eksportować ## Buttons button-cancel = Přetorhnyć button-back = Wróćo button-continue = Dale +button-export = Eksportować ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Z { $app } importować @@ -26,17 +33,52 @@ profile-file-picker-dir = Wubjerće profilowy rjadowak profile-file-picker-zip = Wubjerće zip-dataju (mjeńšu hač 2 GB) items-pane-title = Wubjerće, štož ma so importować -items-pane-desc = Importować z +items-pane-source = Žórłowe městno: items-pane-checkbox-accounts = Konta a nastajenja items-pane-checkbox-address-books = Adresniki items-pane-checkbox-calendars = Protyki items-pane-checkbox-mail-messages = Mejlki +## Import from address book file steps + +import-from-addr-book-file-desc = Wubjerće dataju, kotruž chceće importować: +addr-book-csv-file = Dataja dźělena přez komu abo rajtark (.csv, .tsv) +addr-book-ldif-file = Dataja LDIF (.ldif) +addr-book-vcard-file = Dataja vCard (.vcf, .vcard) +addr-book-sqlite-file = Dataja datoweje banki SQLite (.sqlite) +addr-book-mab-file = Dataja datoweje banki Mork (.mab) +addr-book-file-picker = Adresnikowu dataju wubrać +addr-book-csv-field-map-title = Pólnym mjenam wotpowědować +addr-book-csv-field-map-desc = Wubjerće pola adresnika, kotrež žórłowym polam wotpowěduja. Znjemóžńće pola, kotrež nochceće importować. +addr-book-directories-pane-title = Wubjerće zapis, kotryž byšće rady importował do: +addr-book-directories-pane-source = Žórłowa dataja: +addr-book-import-into-new-directory = Nowy zapis załožić + ## Import dialog progress-pane-title = Importowanje +progress-pane-importing = Importowanje +progress-pane-exporting = Eksportowanje +progress-pane-finished-desc = Dokónčene. progress-pane-restart-desc = Startujće znowa, zo byšće importowanje dokónčił. error-pane-title = Zmylk error-message-zip-file-too-big = Wubrana zip-dataja je wjetša hač 2 GB. Prošu rozpakujće ju najprjedy, a importujće wobsah z rozpakowaneho rjadowaka město toho. error-message-extract-zip-file-failed = Zip-dataja njeda so rozbalić. Prošu wupakujće ju manuelnje a importujće ju potom město toho z ekstrahowaneho rjadowaka. error-message-failed = Importowanje je so njenadźicy nimokuliło, dalše informacije namakaće snano w zmylkowej konsoli. +error-export-failed = Eksportowanje je so njenadźicy nimokuliło, dalše informacije namakaće snano w zmylkowej konsoli. + +## element + +csv-first-row-contains-headers = Prěnja linka mjena polow wobsahuje +csv-source-field = Žórłowe polo +csv-source-first-record = Prěnja datowa sadźba +csv-source-second-record = Druha datowa sadźba +csv-target-field = Polo adresnika + +## Export tab + +export-profile-desc = Eksportujće e-mejlowe konta, mejlki, adresniki, nastajenja do zip-dataje. Jeli trjeba, móžeće zip-dataju importować, zo byšće swój profil wobnowił. +export-profile-desc2 = Jeli waš aktualny profil je wjetši hač 2 GB, namjetujemy, zo jón zawěsćeće. +export-open-profile-folder = Profilowy rjadowak wočinić +export-file-picker = Jako zip-dataju eksportować +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Nowy CardDAV-adresnik - +carddav-window-title = Nowy CardDAV-adresnik carddav-dialog = .buttonlabelaccept = Dale .buttonaccesskeyaccept = D - carddav-username-label = .value = Wužiwarske mjeno: .accesskey = u - carddav-location-label = .value = Městno: .accesskey = M carddav-location = .default-placeholder = URL abo hostowe mjeno adresnikoweho serwera - carddav-loading = Konfiguracija so přepytuje… carddav-known-incompatible = { $url } je za to znaty, zo je inkompatibleny z { -brand-short-name }. carddav-connection-error = Zwisk móžny njeje. carddav-none-found = Njejsu adresniki, kotrež dadźa so wěstemu kontu přidać. carddav-already-added = Wšě adresniki za podate konto su so hižo přidali. - carddav-available-books = K dispoziciji stejace adresniki: diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -144,8 +144,8 @@ about-addressbook-details-home-address-header = Priwatna adresa about-addressbook-details-work-address-header = Słužbna adresa about-addressbook-details-other-info-header = Druhe informacije -about-addressbook-prompt-to-save-title = Změny składować? -about-addressbook-prompt-to-save = Chceće swoje změny składować? +about-addressbook-unsaved-changes-prompt-title = Njeskładowane změny +about-addressbook-unsaved-changes-prompt = Chceće swoje změny składować, prjedy hač wobdźěłowanski napohlad wopušćeće? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:53:43.000000000 +0000 @@ -93,6 +93,15 @@ .tooltiptext = Wobłuk přiwěškow pokazać ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = Wobłuk přiwěškow schować ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } přiwěšk + [one] { $count } přiwěšk + [two] { $count } přiwěškaj + [few] { $count } přiwěški + *[other] { $count } přiwěškow + } attachment-area-show = .title = Wobłuk přiwěškow pokazać ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -256,8 +265,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Tekstowy stil wotstronić -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Je so do njeznateho konta Filelink nahrało. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } - přiwěšk Filelink +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = Dataja { $filename } je so jako Filelink připowěsnyła. Da so z pomocu slědowaceho wotkaza sćahnyć. # Template @@ -272,24 +294,27 @@ *[other] Sym { $count } datajow z tutej mejlku zwjazał: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Dalše informacije wo { $lastLink }. - [two] Dalše informacije wo { $firstLinks } a { $lastLink }. - [few] Dalše informacije wo { $firstLinks } a { $lastLink }. - *[other] Dalše informacije wo { $firstLinks } a { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Dalše informacije wo { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Dalše informacije wo { $firstLinks } a { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Přez hesło škitany wotkaz # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = Słužba CloudFile: +cloud-file-template-service-name = Słužba Filelink: cloud-file-template-size = Wulkosć: cloud-file-template-link = Wotkaz cloud-file-template-password-protected-link = Přez hesło škitany wotkaz: @@ -313,3 +338,9 @@ cloud-file-rename-error-with-custom-message-title = Přemjenowanje { $filename } na { $provider } njeje so poradźiło # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = { $provider } přemjenowanje hižo nahratych datajow njepodpěruje. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Přiwěškowy zmylk Filelink +cloud-file-attachment-error = Přiwěšk { $filename } Filelink njeda so aktualizować, dokelž jeho lokalna dataja je so přesunyła abo zhašała. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Kontowy zmylk Filelink +cloud-file-account-error = Přiwěšk { $filename } Filelink njeda so aktualizować, dokelž jeho lokalna dataja je so zhašała. diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/messenger.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/messenger.ftl 2022-04-15 07:53:43.000000000 +0000 @@ -42,8 +42,8 @@ .label = Spěšny filter .tooltiptext = Powěsće filtrować redirect-msg-button = - .label = Dale sposrědkować - .tooltiptext = Wubranu powěsć dale sposrědkować + .label = Hinak wodźić + .tooltiptext = Wubranu powěsć hinak wodźić ## Folder Pane @@ -81,8 +81,8 @@ ## Menu redirect-msg-menuitem = - .label = Dale sposrědkować - .accesskey = D + .label = Hinak wodźić + .accesskey = H menu-file-save-as-file = .label = Dataja… .accesskey = D @@ -106,12 +106,12 @@ appmenu-help-more-troubleshooting-info = .label = Dalše informacije za rozrisowanje problemow appmenu-redirect-msg = - .label = Dale sposrědkować + .label = Hinak wodźić ## Context menu context-menu-redirect-msg = - .label = Dale sposrědkować + .label = Hinak wodźić mail-context-delete-messages = .label = { $count -> @@ -127,7 +127,7 @@ ## Message header pane other-action-redirect-msg = - .label = Dale sposrědkować + .label = Hinak wodźić message-header-msg-flagged = .title = Z hwěžku .aria-label = Z hwěžku @@ -192,3 +192,64 @@ .title = K rajtarkej nastajenjow přeńć spaces-toolbar-button-collapse = .title = Lajstu dźělnych programow schować +spaces-toolbar-button-reveal = + .title = Lajstu dźělnych programow pokazać +spaces-context-new-tab-item = + .label = W nowym rajtarku wočinić +spaces-context-new-window-item = + .label = W nowym woknje wočinić +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = K { $tabName } přeńć +settings-context-open-settings-item = + .label = Nastajenja wočinić +settings-context-open-account-settings-item = + .label = Kontowe nastajenja wočinić +settings-context-open-addons-item = + .label = Přidatki a drasty wočinić + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Meni dźělnych programow wočinić +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [one] { $count } nječitana powěsć + [two] { $count } nječitanej powěsći + [few] { $count } nječitane powěsće + *[other] { $count } nječitanych powěsćow + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Přiměrić… +spaces-customize-panel-title = Nastajenja lajsty dźělnych programow +spaces-customize-background-color = Pozadkowa barba +spaces-customize-icon-color = Tłóčatkowa barba +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Pozadkowa barba wubraneho tłóčatka +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Barba wubraneho tłóčatka +spaces-customize-button-restore = Standard wobnowić + .accesskey = b +spaces-customize-button-save = Dokónčeny + .accesskey = D diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -16,15 +16,13 @@ .label = Podrobnosće wočinić a akceptancu wobdźěłać… openpgp-one-recipient-status-discover = .label = Nowy abo zaktualizowany kluč namakać - openpgp-one-recipient-status-instruction1 = Zo byšće přijimarjej powěsć zaklučowanu kónc do kónca pósłał, dyrbiće sej jeho zjawny OpenPGP-kluč wobstarać a jón jako akceptowany markěrować. openpgp-one-recipient-status-instruction2 = Zo byšće jeho zjawny kluč dóstał, importujće jeho z mejlki, kotruž je wam pósłał a to jón zasadźi. Alternatiwnje móžeće spytać, jeho zjawny kluč w zapisu namakać. - openpgp-key-own = Akceptowany (wosobinski kluč) openpgp-key-secret-not-personal = Njewužiwajomny openpgp-key-verified = Akceptowany (wobkrućeny) openpgp-key-unverified = Akceptowany (njewobkrućeny) openpgp-key-undecided = Njeakceptowany (njerozsudźeny) openpgp-key-rejected = Njeakceptowany (wotpokazany) - +openpgp-key-expired = Spadnjeny openpgp-intro = K dispoziciji stejace zjawne kluče za { $key } diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/otr/add-finger.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/otr/add-finger.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = Porstowy wotćišć OTR-kluča přidać - +otr-add-finger-title = Porstowy wotčišć OTR-kluča přidać # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Zapodajće porstowy wotćišć OTR-kluča za { $name }. - otr-add-finger-fingerprint = Porstowy wotćišć: otr-add-finger-tooltip-error = Njepłaćiwe znamješko je so zapodało. Jenož pismiki ABCDEF a ličby su dowolene - otr-add-finger-input = .placeholder = 40 znamješkow dołhi porstowy wotćišć OTR-kluča diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/otr/finger.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/otr/finger.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Začinić .title = Do toho widźane porstowe wotćišće OTR - +otr-finger-title = Do toho widźane porstowe wotćišće OTR finger-intro = Porstowe wotćišće OTR-kluča z předchadnych rozmołwow wot kónca do kónca. - finger-screen-name = .label = Kontakt finger-verified = .label = Přepruwowanski status finger-fingerprint = .label = Porstowy wotćišć - finger-remove = .label = Wubrane wotstronić - finger-remove-all = .label = Wšě wotstronić diff -Nru thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/hsb/mail/messenger/preferences/preferences.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/mail/messenger/preferences/preferences.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -116,9 +116,6 @@ .label = Standard wobnowić .accesskey = b default-search-engine = Standardna pytawa -add-search-engine = - .label = Z dataje přidać - .accesskey = Z add-web-search-engine = .label = Přidać… .accesskey = P @@ -196,6 +193,9 @@ smooth-scrolling-label = .label = Łahodne přesuwanje wužiwać .accesskey = h +browsing-gtk-use-non-overlay-scrollbars = + .label = Suwanske lajsty přeco pokazać + .accesskey = u system-integration-legend = Systemowa integracija always-check-default = .label = Při startowanju přeco kontrolować, hač { -brand-short-name } je standardny e-mejlowy program @@ -320,12 +320,6 @@ .accesskey = B search-handler-table = .placeholder = Wobsahowe typy a akcije filtrować -type-column-label = - .label = Typ wobsaha - .accesskey = T -action-column-label = - .label = Akcija - .accesskey = A type-column-header = Wobsahowy typ action-column-header = Akcija save-to-label = diff -Nru thunderbird-91.7.0+build2/l10n/hsb/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/hsb/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/hsb/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:53:42.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Sans-serif # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Čitanski napohlad začinić @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Swětła barbowa šema aboutReader.toolbar.colorschemedark = Ćmowa barbowa šema aboutReader.toolbar.colorschemesepia = Barbowa šema Sepia +aboutReader.toolbar.colorschemeauto = Awtomatiska barbowa šema diff -Nru thunderbird-91.7.0+build2/l10n/hsb/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/hsb/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/hsb/toolkit/chrome/global/narrate.properties 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/toolkit/chrome/global/narrate.properties 2022-04-15 07:53:42.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Słuchać back = Wróćo start = Započeć stop = Zastajić +# %S is the keyboard shortcut for the start command +start-label = Startować (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Zastajić (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Doprědka speed = Spěšnosć selectvoicelabel = Hłós: diff -Nru thunderbird-91.7.0+build2/l10n/hsb/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/hsb/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/hsb/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -185,6 +185,26 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } wobłuk + [two] { $frames } wobłukaj + [few] { $frames } wobłuki + *[other] { $frames } wobłukow + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } kanal + [two] { $channels } kanalej + [few] { $channels } kanale + *[other] { $channels } kanalow + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/hsb/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/hsb/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/hsb/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:38:41.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hsb/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:53:42.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Adresowe polo: wuslědki za IME-kompoziciju pokazać experimental-features-ime-search-description = IME (Input Method Editor, editor zapodawanskeje metody) je nastroj, kotryž wam zmóžnja, kompleksne symbole zapodać, kaž so na přikład we wuchodoaziskich abo indiskich rěčach wužiwaja, z pomocu standardneje tastatury. Hdyž tutón eksperiment zmóžnjeće, wostawa wokno adresoweho pola wočinjene, kotrež pytanske wuslědki a namjety pokazuje, mjeztym zo tekst z pomocu IME zapodawaće. Dźiwajće na to, zo móhł IME wokno pokazać, kotrež wuslědki adresoweho pola wobsahuje, tohodla so tute nastajenje jenož za IME namjetuje, kotryž tutón typ wokna njewužiwa. +# Firefox 100 +experimental-features-firefox-100 = + .label = Znamješkowy rjećazk user-agent { -brand-product-name } 100 +experimental-features-firefox-100-description = Dajće { -brand-short-name } websydłam znamješkowy rjećazk user agent słać, kotryž wudawa, zo so wo wersiju 100 { -brand-product-name } jedna. Wužiwajće tute nastajenje, zo byšće testował, hač so websydła wobškodźeja, hdyž { -brand-short-name } ma třiměstnowe wersijowe čisło. Wozjewjenje woprawdźiteho { -brand-product-name } 100 je za meju 2022 planowane, testujće potajkim swoje websydła nětko! diff -Nru thunderbird-91.7.0+build2/l10n/hu/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/hu/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/hu/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Adatvédelem: Privát esemény calendar-editable-item-privacy-icon-confidential = .alt = Adatvédelem: Csak az idő és a dátum megjelenítése +calendar-editable-item-recurrence = + .alt = Ismétlődő +calendar-editable-item-recurrence-exception = + .alt = Ismétlődési kivétel calendar-editable-item-todo-icon-task = .alt = Feladat calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/hu/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/hu/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/hu/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:53:52.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } meghívta Önt a következőre: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Mentés +calendar-invitation-panel-accept-button = Igen +calendar-invitation-panel-decline-button = Nem +calendar-invitation-panel-tentative-button = Talán +calendar-invitation-panel-reply-status = * Még nem döntött vagy nem válaszolt +calendar-invitation-panel-prop-title-when = Mikor: +calendar-invitation-panel-prop-title-location = Hely: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Résztvevők: +calendar-invitation-panel-prop-title-description = Leírás: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } igen + [DECLINED] { $count } nem + [TENTATIVE] { $count } talán + [NEEDS-ACTION] { $count } függőben + [TOTAL] { $count } résztvevő + *[OTHER] { $count } egyéb + } diff -Nru thunderbird-91.7.0+build2/l10n/hu/chat/matrix.properties thunderbird-91.8.1+build1/l10n/hu/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/hu/chat/matrix.properties 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/chat/matrix.properties 2022-04-15 07:53:50.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S a további okkal megszakította az ellenőrzést: %2$S message.verification.done=Az ellenőrzés befejeződött. +message.decryptionError=Nem sikerült visszafejteni az üzenet tartalmát. Ha titkosítási kulcsot szeretne kérni más eszközeiről, kattintson a jobb gombbal erre az üzenetre. +message.decrypting=Visszafejtés… +message.redacted=Az üzenetet törölték. + +# Label in the message context menu +message.action.requestKey=Kulcsok újbóli kérése +message.action.redact=Törlés +message.action.report=Üzenet jelentése +message.action.retry=Küldés újrapróbálása +message.action.cancel=Üzenet megszakítása + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Hiba történt a(z) „%1$S” üzenet elküldése során. diff -Nru thunderbird-91.7.0+build2/l10n/hu/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/hu/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/hu/devtools/client/aboutdebugging.ftl 2022-03-07 21:38:48.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/devtools/client/aboutdebugging.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -10,7 +10,6 @@ # Page title (ie tab title) for the Setup page about-debugging-page-title-setup-page = Hibakeresés – Beállítás - # Page title (ie tab title) for the Runtime page # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ... about-debugging-page-title-runtime-page = Hibakeresés – Futtatókörnyezet / { $selectedRuntimeId } @@ -20,56 +19,42 @@ # Display name of the runtime for the currently running instance of Firefox. Used in the # Sidebar and in the Setup page. about-debugging-this-firefox-runtime-name = Ez a { -brand-shorter-name } - # Sidebar heading for selecting the currently running instance of Firefox about-debugging-sidebar-this-firefox = .name = { about-debugging-this-firefox-runtime-name } - # Sidebar heading for connecting to some remote source about-debugging-sidebar-setup = .name = Beállítások - # Text displayed in the about:debugging sidebar when USB devices discovery is enabled. about-debugging-sidebar-usb-enabled = USB engedélyezve - # Text displayed in the about:debugging sidebar when USB devices discovery is disabled # (for instance because the mandatory ADB extension is not installed). about-debugging-sidebar-usb-disabled = USB letiltva - # Connection status (connected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-connected = Kapcsolódva # Connection status (disconnected) for runtime items in the sidebar aboutdebugging-sidebar-runtime-connection-status-disconnected = Bontva - # Text displayed in the about:debugging sidebar when no device was found. about-debugging-sidebar-no-devices = Nincs felfedezett eszköz - # Text displayed in buttons found in sidebar items representing remote runtimes. # Clicking on the button will attempt to connect to the runtime. about-debugging-sidebar-item-connect-button = Kapcsolódás - # Text displayed in buttons found in sidebar items when the runtime is connecting. about-debugging-sidebar-item-connect-button-connecting = Kapcsolódás… - # Text displayed in buttons found in sidebar items when the connection failed. about-debugging-sidebar-item-connect-button-connection-failed = Kapcsolódás sikertelen - # Text displayed in connection warning on sidebar item of the runtime when connecting to # the runtime is taking too much time. about-debugging-sidebar-item-connect-button-connection-not-responding = A kapcsolódás még függőben van, ellenőrizze a célböngésző üzeneteit - # Text displayed as connection error in sidebar item when the connection has timed out. about-debugging-sidebar-item-connect-button-connection-timeout = A kapcsolat időtúllépés miatt megszakadt. - # Text displayed in sidebar items for remote devices where a compatible browser (eg # Firefox) has not been detected yet. Typically, Android phones connected via USB with # USB debugging enabled, but where Firefox is not started. about-debugging-sidebar-runtime-item-waiting-for-browser = Várakozás a böngészőre… - # Text displayed in sidebar items for remote devices that have been disconnected from the # computer. about-debugging-sidebar-runtime-item-unplugged = Leválasztva - # Title for runtime sidebar items that are related to a specific device (USB, WiFi). about-debugging-sidebar-runtime-item-name = .title = { $displayName } ({ $deviceName }) @@ -77,16 +62,13 @@ # locations). about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } - # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Hibakeresési támogatás - # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar about-debugging-sidebar-support-icon = .alt = Súgó ikon - # Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it # will attempt to update the list of devices displayed in the sidebar. about-debugging-refresh-usb-devices-button = Eszközök frissítése @@ -95,83 +77,61 @@ # Title of the Setup page. about-debugging-setup-title = Beállítások - # Introduction text in the Setup page to explain how to configure remote debugging. about-debugging-setup-intro = Állítsa be a kapcsolódási módot, amellyel távolról akar hibát keresni a készüléken. - # Explanatory text in the Setup page about what the 'This Firefox' page is for about-debugging-setup-this-firefox2 = Használja a { about-debugging-this-firefox-runtime-name } lehetőséget a kiegészítők és service workerek hibakeresésére a { -brand-shorter-name } ezen verzióján. - # Title of the heading Connect section of the Setup page. about-debugging-setup-connect-heading = Eszköz csatlakoztatása - # USB section of the Setup page about-debugging-setup-usb-title = USB - # Explanatory text displayed in the Setup page when USB debugging is disabled about-debugging-setup-usb-disabled = Ennek engedélyezése letölti és hozzáadja a szükséges Android USB hibakeresési összetevőket a { -brand-shorter-name }hoz. - # Text of the button displayed in the USB section of the setup page when USB debugging is disabled. # Clicking on it will download components needed to debug USB Devices remotely. about-debugging-setup-usb-enable-button = USB-eszközök engedélyezése - # Text of the button displayed in the USB section of the setup page when USB debugging is enabled. about-debugging-setup-usb-disable-button = USB-eszközök letiltása - # Text of the button displayed in the USB section of the setup page while USB debugging # components are downloaded and installed. about-debugging-setup-usb-updating-button = Frissítés… - # USB section of the Setup page (USB status) about-debugging-setup-usb-status-enabled = Engedélyezve about-debugging-setup-usb-status-disabled = Tiltva about-debugging-setup-usb-status-updating = Frissítés… - # USB section step by step guide about-debugging-setup-usb-step-enable-dev-menu2 = Engedélyezze a fejlesztői menüt az androidos eszközén. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug2 = Engedélyezze az USB-s hibakeresést az androidos fejlesztői menüben. - # USB section step by step guide about-debugging-setup-usb-step-enable-debug-firefox2 = Engedélyezze az USB-s hibakeresést a Firefoxban az androidos eszközén. - # USB section step by step guide about-debugging-setup-usb-step-plug-device = Csatlakoztassa az androidos eszközt a számítógépéhez. - # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Problémája van az USB-s eszköz csatlakoztatásakor? Hibaelhárítás - # Network section of the Setup page about-debugging-setup-network = .title = Hálózat helye - # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Problémája van a hálózati helyhez csatlakozáskor? Hibaelhárítás - # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. about-debugging-network-locations-add-button = Hozzáadás - # Text to display when there are no locations to show. about-debugging-network-locations-empty-text = Még nincsenek hálózati helyek hozzáadva. - # Text of the label for the text input that allows users to add new network locations in # the Connect page. A host is a hostname and a port separated by a colon, as suggested by # the input's placeholder "localhost:6080". about-debugging-network-locations-host-input-label = Gép - # Text of a button displayed next to existing network locations in the Connect page. # Clicking on it removes the network location from the list. about-debugging-network-locations-remove-button = Eltávolítás - # Text used as error message if the format of the input value was invalid in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form about-debugging-network-location-form-invalid = Érvénytelen gazda: „{ $host-value }”. A várt formátum: „gépnév:portszám”. - # Text used as error message if the input value was already registered in the network locations form of the Setup page. # Variables: # $host-value (string) - The input value submitted by the user in the network locations form @@ -202,54 +162,43 @@ # Title of the processes category. about-debugging-runtime-processes = .name = Folyamatok - # Label of the button opening the performance profiler panel in runtime pages for remote # runtimes. about-debugging-runtime-profile-button2 = Profil teljesítménye - # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = A böngésző beállításai nem kompatibilisek a Service Workerekkel. További információk - # This string is displayed in the runtime page if the remote browser version is too old. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format) about-debugging-browser-version-too-old = A csatlakoztatott böngésző régi verziójú ({ $runtimeVersion }). A minimális támogatott verzió: ({ $minVersion }). Ez egy nem támogatott összeállítás és a fejlesztői eszközök hibáját okozhatja. Frissítse a csatlakoztatott böngészőt. Hibaelhárítás - # Dedicated message for a backward compatibility issue that occurs when connecting: # from Fx 70+ to the old Firefox for Android (aka Fennec) which uses Fx 68. about-debugging-browser-version-too-old-fennec = A Firefox ezen verziója nem tud hibát keresni a Firefox for Androidban (68). Javasoljuk, hogy a teszteléshez telepítse a Firefox for Android Nightlyt a telefonjára. További részletek - # This string is displayed in the runtime page if the remote browser version is too recent. -# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting +# "Troubleshooting" link points to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/ # { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd) # { $localID } is the build ID of the current Firefox instance (same format) # { $runtimeVersion } is the version of the remote browser (for instance "67.0a1") # { $localVersion } is the version of your current browser (same format) about-debugging-browser-version-too-recent = A csatlakoztatott böngésző frissebb ({ $runtimeVersion }, összeállítási azonosító: { $runtimeID }) mint az Ön { -brand-shorter-name }a ({ $localVersion }, összeállítási azonosító: { $localID }). Ez egy nem támogatott összeállítás és a fejlesztői eszközök hibáját okozhatja. Frissítse a csatlakoztatott böngészőt. Frissítse a Firefoxot. Hibaelhárítás - # Displayed for runtime info in runtime pages. # { $name } is brand name such as "Firefox Nightly" # { $version } is version such as "64.0a1" about-debugging-runtime-name = { $name } ({ $version }) - # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Kapcsolat bontása - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is false on the target runtime. about-debugging-connection-prompt-enable-button = Kapcsolódási kérdés engedélyezése - # Text of the connection prompt button displayed in Runtime pages, when the preference # "devtools.debugger.prompt-connection" is true on the target runtime. about-debugging-connection-prompt-disable-button = Kapcsolódási kérdés letiltása - # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button. about-debugging-profiler-dialog-title2 = Profilkészítő - # Clicking on the header of a debug target category will expand or collapse the debug # target items in the category. This text is used as ’title’ attribute of the header, # to describe this feature. @@ -260,131 +209,114 @@ # Displayed in the categories of "runtime" pages that don't have any debug target to # show. Debug targets depend on the category (extensions, tabs, workers...). about-debugging-debug-target-list-empty = Még nincs. - # Text of a button displayed next to debug targets of "runtime" pages. Clicking on this # button will open a DevTools toolbox that will allow inspecting the target. # A target can be an addon, a tab, a worker... about-debugging-debug-target-inspect-button = Vizsgálat - # Text of a button displayed in the "This Firefox" page, in the Temporary Extension # section. Clicking on the button will open a file picker to load a temporary extension about-debugging-tmp-extension-install-button = Ideiglenes kiegészítő betöltése… - # Text displayed when trying to install a temporary extension in the "This Firefox" page. about-debugging-tmp-extension-install-error = Hiba történt az ideiglenes kiegészítő telepítésekor. - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will reload the extension. about-debugging-tmp-extension-reload-button = Újratöltés - # Text of a button displayed for a temporary extension loaded in the "This Firefox" page. # Clicking on the button will uninstall the extension and remove it from the page. about-debugging-tmp-extension-remove-button = Eltávolítás - +# Text of a button displayed for a temporary extension loaded in the "This Firefox" page. +# Clicking on the button will forcefully terminate the extension background script (button +# only visible in extensions that includes a non-persistent background script, either an +# event page or a background service worker). +about-debugging-tmp-extension-terminate-bgscript-button = Háttérben futó parancsfájl leállítása # Message displayed in the file picker that opens to select a temporary extension to load # (triggered by the button using "about-debugging-tmp-extension-install-button") # manifest.json .xpi and .zip should not be localized. # Note: this message is only displayed in Windows and Linux platforms. about-debugging-tmp-extension-install-message = Válassza ki a manifest.json fájlt vagy egy .xpi/.zip archívumot - # This string is displayed as a message about the add-on having a temporaryID. about-debugging-tmp-extension-temporary-id = Ez a WebExtension ideiglenes azonosítóval rendelkezik. További információ - # Text displayed for extensions in "runtime" pages, before displaying a link the extension's # manifest URL. about-debugging-extension-manifest-url = .label = Jegyzékfájl URL - # Text displayed for extensions in "runtime" pages, before displaying the extension's uuid. # UUIDs look like b293e463-481e-5148-a487-5aaf7a130429 about-debugging-extension-uuid = .label = Belső UUID - # Text displayed for extensions (temporary extensions only) in "runtime" pages, before # displaying the location of the temporary extension. about-debugging-extension-location = .label = Hely - # Text displayed for extensions in "runtime" pages, before displaying the extension's ID. # For instance "geckoprofiler@mozilla.com" or "{ed26ddcb-5611-4512-a89a-51b8db81cfb2}". about-debugging-extension-id = .label = Kiegészítőazonosító - +# Text displayed for extensions in "runtime" pages, before displaying the status of the +# extension background script. +about-debugging-extension-backgroundscript = + .label = Háttérben futó parancsfájl +# Displayed for extension using a non-persistent background page (either an event page or +# background service worker) when the background script is currently running. +about-debugging-extension-backgroundscript-status-running = Fut +# Displayed for extension using a non-persistent background page when is currently stopped. +about-debugging-extension-backgroundscript-status-stopped = Leállítva # This string is displayed as a label of the button that pushes a test payload # to a service worker. # Note this relates to the "Push" API, which is normally not localized so it is # probably better to not localize it. about-debugging-worker-action-push2 = Push üzenetek .disabledTitle = A Service Worker push üzenetek jelenleg le vannak tiltva a többfolyamatos { -brand-shorter-name }ban - # This string is displayed as a label of the button that starts a service worker. about-debugging-worker-action-start2 = Kezdés .disabledTitle = A Service Worker indítása jelenleg le van tiltva a többfolyamatos { -brand-shorter-name }ban - # This string is displayed as a label of the button that unregisters a service worker. about-debugging-worker-action-unregister = Regisztráció megszüntetése - # Displayed for service workers in runtime pages that listen to Fetch events. about-debugging-worker-fetch-listening = .label = Fetch .value = Fetch események figyelése - # Displayed for service workers in runtime pages that do not listen to Fetch events. about-debugging-worker-fetch-not-listening = .label = Fetch .value = Fetch események figyelése - # Displayed for service workers in runtime pages that are currently running (service # worker instance is active). about-debugging-worker-status-running = Fut - # Displayed for service workers in runtime pages that are registered but stopped. about-debugging-worker-status-stopped = Leállítva - # Displayed for service workers in runtime pages that are registering. about-debugging-worker-status-registering = Regisztráció - # Displayed for service workers in runtime pages, to label the scope of a worker about-debugging-worker-scope = .label = Hatáskör - # Displayed for service workers in runtime pages, to label the push service endpoint (url) # of a worker about-debugging-worker-push-service = .label = Küldési szolgáltatás - # Displayed as title of the inspect button when service worker debugging is disabled. about-debugging-worker-inspect-action-disabled = .title = A Service Worker ellenőrzés jelenleg le van tiltva a többfolyamatos { -brand-shorter-name }ban. - # Displayed as title of the inspect button for zombie tabs (e.g. tabs loaded via a session restore). about-debugging-zombie-tab-inspect-action-disabled = .title = A lap nincs teljesen betöltve, és nem vizsgálható - # Displayed as name for the Main Process debug target in the Processes category. Only for # remote runtimes, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-name = Fő folyamat - # Displayed as description for the Main Process debug target in the Processes category. # Only for remote browsers, if `devtools.aboutdebugging.process-debugging` is true. about-debugging-main-process-description2 = A célböngésző fő folyamata - # Displayed instead of the Main Process debug target when the preference # `devtools.browsertoolbox.fission` is true. about-debugging-multiprocess-toolbox-name = Többfolyamatos eszköztár - # Description for the Multiprocess Toolbox target. about-debugging-multiprocess-toolbox-description = Fő folyamat és tartalomfolyamatok a cél böngészőhöz - # Alt text used for the close icon of message component (warnings, errors and notifications). about-debugging-message-close-icon = .alt = Üzenet bezárása - # Label text used for the error details of message component. about-debugging-message-details-label-error = Hiba részletei - # Label text used for the warning details of message component. about-debugging-message-details-label-warning = Figyelmeztetés részletei - # Label text used for default state of details of message component. about-debugging-message-details-label = Részletek diff -Nru thunderbird-91.7.0+build2/l10n/hu/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/hu/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/hu/devtools/client/compatibility.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/devtools/client/compatibility.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -14,7 +14,6 @@ compatibility-issue-experimental = (kísérleti) compatibility-issue-prefixneeded = (előtag szükséges) compatibility-issue-deprecated-experimental = (elavult, kísérleti) - compatibility-issue-deprecated-prefixneeded = (elavult, előtag szükséges) compatibility-issue-experimental-prefixneeded = (kísérleti, előtag szükséges) compatibility-issue-deprecated-experimental-prefixneeded = (elavult, kísérleti, előtag szükséges) @@ -43,7 +42,14 @@ [one] { $number } előfordulás *[other] { $number } előfordulás } - compatibility-no-issues-found = Nem található kompatibilitási probléma. compatibility-close-settings-button = .title = Beállítások bezárása +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Kompatibilitási problémák itt: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/hu/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/hu/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/hu/devtools/client/netmonitor.properties 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/devtools/client/netmonitor.properties 2022-04-15 07:53:50.000000000 +0000 @@ -162,6 +162,11 @@ # in the response tab of the network details pane for a JSONP scope. jsonpScopeName=JSONP → visszahívás %S() +# LOCALIZATION NOTE (jsonXssiStripped): This is the text displayed +# in a notification in the response tab of the network details pane +# when a JSON payload had XSSI escape characters which were removed +jsonXssiStripped=A(z) „%S” karakterlánc eltávolításra került az alábbi JSON elejéről + # LOCALIZATION NOTE (responseTruncated): This is the text displayed # in the response tab of the network details pane when the response is over # the truncation limit and thus was truncated. @@ -1460,10 +1465,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=Lekérdezés karakterlánc: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=URL-paraméterek + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Kérés fejlécei: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Fejlécek + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=név + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=érték + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Törzs + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=hasznos forgalom + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Kérés törzse: @@ -1476,6 +1505,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Mégse +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Törlés + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Elem eltávolítása + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Vissza diff -Nru thunderbird-91.7.0+build2/l10n/hu/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/hu/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/hu/devtools/client/toolbox-options.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/devtools/client/toolbox-options.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -104,6 +104,10 @@ options-enable-remote-label = Távoli hibakeresés be/ki options-enable-remote-tooltip2 = .title = A beállítás bekapcsolásával engedélyezi a böngészőpéldány távoli hibakeresését. +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Egyéni formázók engedélyezése +options-enable-custom-formatters-tooltip = + .title = A beállítás bekapcsolásával a webhelyek egyéni formázókat határozhatnak meg a DOM-objektumokhoz # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = A Service Workers bekapcsolása HTTP-n (ha az eszköztár nyitva van) options-enable-service-workers-http-tooltip = diff -Nru thunderbird-91.7.0+build2/l10n/hu/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/hu/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/hu/devtools/client/webconsole.properties 2022-03-07 21:38:48.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/devtools/client/webconsole.properties 2022-04-15 07:53:50.000000000 +0000 @@ -228,6 +228,19 @@ # the output of the console. webconsole.menu.exportSubmenu.exportFile.label=Fájl +# LOCALIZATION NOTE (webconsole.menu.copyAllMessages.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# copies the entire output of the console to the clipboard. +webconsole.menu.copyAllMessages.label=Összes üzenet másolása +webconsole.menu.copyAllMessages.accesskey=m + +# LOCALIZATION NOTE (webconsole.menu.saveAllMessagesFile.label) +# Label used for a context-menu item displayed on the output. Clicking on it +# opens a file picker to allow the user save a file containing +# the output of the console. +webconsole.menu.saveAllMessagesFile.label=Összes üzenet fájlba mentése +webconsole.menu.saveAllMessagesFile.accesskey=f + # LOCALIZATION NOTE (webconsole.clearButton.tooltip) # Label used for the tooltip on the clear logs button in the console top toolbar bar. # Clicking on it will clear the content of the console. diff -Nru thunderbird-91.7.0+build2/l10n/hu/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/hu/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/hu/dom/chrome/dom/dom.properties 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/dom/chrome/dom/dom.properties 2022-04-15 07:53:52.000000000 +0000 @@ -39,6 +39,9 @@ FormValidationInvalidURL=Írjon be egy URL-t. FormValidationInvalidDate=Adjon meg egy érvényes dátumot. FormValidationInvalidTime=Írjon be egy érvényes időpontot. +FormValidationInvalidDateTime=Adjon meg egy érvényes dátumot és időt. +FormValidationInvalidDateMonth=Adjon meg egy érvényes hónapot. +FormValidationInvalidDateWeek=Adjon meg egy érvényes hetet. FormValidationPatternMismatch=A kért formátumban adja meg az adatot. # LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value. FormValidationPatternMismatchWithTitle=A kért formátumban adja meg az adatot: %S. diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/FilterEditor.dtd thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/FilterEditor.dtd --- thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/FilterEditor.dtd 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/FilterEditor.dtd 2022-04-15 07:53:50.000000000 +0000 @@ -27,7 +27,6 @@ - diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/messengercompose/messengercompose.dtd thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/messengercompose/messengercompose.dtd --- thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-03-07 21:38:48.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/messengercompose/messengercompose.dtd 2022-04-15 07:53:50.000000000 +0000 @@ -11,6 +11,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/messenger.dtd thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/messenger.dtd --- thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/messenger.dtd 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/messenger.dtd 2022-04-15 07:53:50.000000000 +0000 @@ -677,7 +677,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/messenger.properties thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/messenger.properties --- thunderbird-91.7.0+build2/l10n/hu/mail/chrome/messenger/messenger.properties 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/chrome/messenger/messenger.properties 2022-04-15 07:53:50.000000000 +0000 @@ -697,7 +697,7 @@ # LOCALIZATION NOTE (downloadAndInstallButton.label): %S is replaced by the # version of the update: "Update to 28.0". update.downloadAndInstallButton.label=Frissítés erre: %S -update.downloadAndInstallButton.accesskey=U +update.downloadAndInstallButton.accesskey=F # Sanitize # LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/aboutDialog.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/aboutDialog.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/aboutDialog.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/aboutDialog.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +about-update-whats-new = Újdonságok diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/aboutImport.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/aboutImport.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/aboutImport.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/aboutImport.ftl 2022-04-15 07:53:52.000000000 +0000 @@ -10,15 +10,22 @@ import-from-app-desc = Fiókok, címjegyzékek, naptárak és egyéb adatok importálása innen: import-address-book = Címjegyzékfájl importálása import-calendar = Naptárfájl importálása +export-profile = Exportálás ## Buttons button-cancel = Mégse button-back = Vissza button-continue = Folytatás +button-export = Exportálás ## Import from app steps +app-name-thunderbird = Thunderbird +app-name-seamonkey = SeaMonkey +app-name-outlook = Outlook +app-name-becky = Becky! Internet Mail +app-name-apple-mail = Apple Mail # Variables: # $app (String) - The name of the app to import from profiles-pane-title = Importálás innen: { $app } @@ -26,17 +33,52 @@ profile-file-picker-dir = Válasszon profilmappát profile-file-picker-zip = Válasszon egy ZIP-fájlt (2 GB-nál kisebbet) items-pane-title = Válasszon, hogy mit szeretne importálni -items-pane-desc = Importálás… +items-pane-source = Forrás helye: items-pane-checkbox-accounts = Fiókok és beállítások items-pane-checkbox-address-books = Címjegyzékek items-pane-checkbox-calendars = Naptárak items-pane-checkbox-mail-messages = Levelek +## Import from address book file steps + +import-from-addr-book-file-desc = Válassza ki az importálandó fájltípust: +addr-book-csv-file = Vesszővel vagy tabulátorral elválasztott fájl (.csv, .tsv) +addr-book-ldif-file = LDIF-fájl (.ldif) +addr-book-vcard-file = vCard-fájl (.vcf, .vcard) +addr-book-sqlite-file = SQLite adatbázisfájl (.sqlite) +addr-book-mab-file = Mork adatbázisfájl (.mab) +addr-book-file-picker = Címjegyzékfájl kiválasztása +addr-book-csv-field-map-title = Mezőnevek összerendelése +addr-book-csv-field-map-desc = Válassza ki a forrásmezőknek megfelelő címjegyzékmezőket. Kapcsolja ki azokat a mezőket, melyeket nem akar importálni. +addr-book-directories-pane-title = Válassza ki az importálás célkönyvtárát: +addr-book-directories-pane-source = Forrásfájl: +addr-book-import-into-new-directory = Új könyvtár létrehozása + ## Import dialog progress-pane-title = Importálás +progress-pane-importing = Importálás +progress-pane-exporting = Exportálás +progress-pane-finished-desc = Kész. progress-pane-restart-desc = Újraindítás az importálás befejezéséhez. error-pane-title = Hiba error-message-zip-file-too-big = A kiválasztott ZIP-fájl nagyobb, mint 2 GB. Először bontsa ki, majd importálja a kibontott mappából. error-message-extract-zip-file-failed = A ZIP-fájl kibontása sikertelen. Bontsa ki kézzel, majd importálja a kibontott mappából. error-message-failed = Az importálás váratlanul meghiúsult, további információ lehet elérhető a Hibakonzolban. +error-export-failed = Az exportálás váratlanul meghiúsult, további információ lehet elérhető a Hibakonzolban. + +## element + +csv-first-row-contains-headers = Az első sor mezőneveket tartalmaz +csv-source-field = Forrásmező +csv-source-first-record = Első rekord +csv-source-second-record = Második rekord +csv-target-field = Címjegyzékmező + +## Export tab + +export-profile-desc = Postafiókok, e-mail üzenetek, címjegyzékek, beállítások ZIP-fájlba exportálása. Ha szükséges, importálhatja a ZIP-fájlt a profil helyreállításához. +export-profile-desc2 = Ha a jelenlegi profilja nagyobb, mint 2 GB, javasoljuk, hogy saját kezűleg készítsen biztonsági másolatot. +export-open-profile-folder = Profilmappa megnyitása +export-file-picker = Exportálás ZIP-fájlba +export-brand-name = { -brand-product-name } diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/addressbook/abCardDAVDialog.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/addressbook/abCardDAVDialog.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/addressbook/abCardDAVDialog.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -4,25 +4,21 @@ carddav-window = .title = Új CardDAV-címjegyzék - +carddav-window-title = Új CardDAV-címjegyzék carddav-dialog = .buttonlabelaccept = Folytatás .buttonaccesskeyaccept = F - carddav-username-label = .value = Felhasználónév: .accesskey = F - carddav-location-label = .value = Hely: .accesskey = H carddav-location = .default-placeholder = A címjegyék-kiszolgáló URL-je vagy gépneve - carddav-loading = Konfiguráció felolvasása… carddav-known-incompatible = A(z) { $url } nem kompatibilis a { -brand-short-name }del. carddav-connection-error = A kapcsolódás sikertelen. carddav-none-found = A megadott fiókhoz nem található címjegyzék. carddav-already-added = A megadott fiókhoz tartozó összes címjegyzék már hozzá lett adva. - carddav-available-books = Elérhető címjegyzékek: diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/addressbook/aboutAddressBook.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/addressbook/aboutAddressBook.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/addressbook/aboutAddressBook.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/addressbook/aboutAddressBook.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -132,8 +132,8 @@ about-addressbook-details-home-address-header = Otthoni cím about-addressbook-details-work-address-header = Munkahelyi cím about-addressbook-details-other-info-header = Egyéb információk -about-addressbook-prompt-to-save-title = Menti a változtatásokat? -about-addressbook-prompt-to-save = Szeretné menteni a módosításokat? +about-addressbook-unsaved-changes-prompt-title = Nem mentett módosítások +about-addressbook-unsaved-changes-prompt = Menti a módosításokat, mielőtt kilép a szerkesztési nézetből? # Photo dialog diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/messengercompose/messengercompose.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/messengercompose/messengercompose.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/messengercompose/messengercompose.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/messengercompose/messengercompose.ftl 2022-04-15 07:53:52.000000000 +0000 @@ -87,6 +87,13 @@ .tooltiptext = A mellékletek ablaktábla megjelenítése ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) collapse-attachment-pane-tooltip = .tooltiptext = A mellékletek ablaktábla elrejtése ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) +# $count (Number) - the number of attachments in the attachment bucket +attachment-bucket-count-value = + { $count -> + [1] { $count } melléklet + [one] { $count } melléklet + *[other] { $count } melléklet + } attachment-area-show = .title = A mellékletek ablaktábla megjelenítése ({ ctrl-cmd-shift-pretty-prefix }{ toggle-attachment-pane-key }) attachment-area-hide = @@ -242,8 +249,21 @@ compose-tool-button-remove-text-styling = .tooltiptext = Szövegstílus eltávolítása -## FileLink +## Filelink +# A text used in a tooltip of Filelink attachments, whose account has been +# removed or is unknown. +cloud-file-unknown-account-tooltip = Egy ismeretlen Filelink-fiókba feltöltve. + +# Placeholder file + +# Title for the html placeholder file. +# $filename - name of the file +cloud-file-placeholder-title = { $filename } – Filelink-melléklet +# A text describing that the file was attached as a Filelink and can be downloaded +# from the link shown below. +# $filename - name of the file +cloud-file-placeholder-intro = A(z) { $filename } fájlt Filelink-hivatkozásként csatolták. Az alábbi hivatkozásról tölthető le. # Template @@ -256,22 +276,27 @@ *[other] { $count } fájlt hivatkoztam ehhez az e-mailhez: } # A text used in a footer, instructing the reader where to find additional -# information about the used service providers. -cloud-file-service-provider-footer = - { $count -> - [one] Tudjon meg többet a következőről: { $lastLink }. - *[other] Tudjon meg többet a következőkről: { $firstLinks } és { $lastLink }. - } +# information about the used service provider. +# $link (string) - html a-tag for a link pointing to the web page of the provider +cloud-file-service-provider-footer-single = Tudjon meg többet a következőről: { $link }. +# A text used in a footer, instructing the reader where to find additional +# information about the used service providers. Links for the used providers are +# split into a comma separated list of the first n-1 providers and a single entry +# at the end. +# $firstLinks (string) - comma separated list of html a-tags pointing to web pages +# of the first n-1 used providers +# $lastLink (string) - html a-tag pointing the web page of the n-th used provider +cloud-file-service-provider-footer-multiple = Tudjon meg többet a következőkről: { $firstLinks } és { $lastLink }. # Tooltip for an icon, indicating that the link is protected by a password. cloud-file-tooltip-password-protected-link = Jelszóval védett hivatkozás # Used in a list of stats about a specific file -# Service - the used service provider to host the file (CloudFile Service: BOX.com) +# Service - the used service provider to host the file (Filelink Service: BOX.com) # Size - the size of the file (Size: 4.2 MB) # Link - the link to the file (Link: https://some.provider.com) # Expiry Date - stating the date the link will expire (Expiry Date: 12.12.2022) # Download Limit - stating the maximum allowed downloads, before the link becomes invalid # (Download Limit: 6) -cloud-file-template-service = CloudFile szolgáltatás: +cloud-file-template-service-name = Filelink szolgáltatás: cloud-file-template-size = Méret: cloud-file-template-link = Hivatkozás: cloud-file-template-password-protected-link = Jelszóval védett hivatkozás: @@ -295,3 +320,9 @@ cloud-file-rename-error-with-custom-message-title = A(z) { $filename } átnevezése a(z) { $provider } szolgáltatásban sikertelen # $provider (string) - name of the online storage service that reported the error cloud-file-rename-not-supported = A(z) { $provider } nem támogatja a már feltöltött fájlok átnevezését. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-attachment-error-title = Filelink melléklethiba +cloud-file-attachment-error = Nem sikerült frissíteni a(z) { $filename } Filelink mellékletet, mert a helyi fájlt áthelyezték vagy törölték. +# $filename (string) - name of the file that was renamed and caused the error +cloud-file-account-error-title = Filelink fiókhiba +cloud-file-account-error = Nem sikerült frissíteni a(z) { $filename } Filelink mellékletet, mert a Filelink-fiókot törölték. diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/messenger.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/messenger.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/messenger.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/messenger.ftl 2022-04-15 07:53:52.000000000 +0000 @@ -188,3 +188,62 @@ .title = Átváltás a beállítások lapra spaces-toolbar-button-collapse = .title = Helyek eszköztár összecsukása +spaces-toolbar-button-reveal = + .title = Helyek eszköztár megjelenítése +spaces-context-new-tab-item = + .label = Megnyitás új lapon +spaces-context-new-window-item = + .label = Megnyitás új ablakban +# Variables: +# $tabName (String) - The name of the tab this item will switch to. +spaces-context-switch-tab-item = + .label = Váltás erre: { $tabName } +settings-context-open-settings-item = + .label = Beállítások megnyitása +settings-context-open-account-settings-item = + .label = Fiókbeállítások megnyitása +settings-context-open-addons-item = + .label = Kiegészítők és témák megnyitása + +## Spaces toolbar pinned tab menupopup + +spaces-toolbar-pinned-tab-button = + .tooltiptext = Helyek menü megnyitása +spaces-pinned-button-menuitem-mail = + .label = { spaces-toolbar-button-mail.title } +spaces-pinned-button-menuitem-address-book = + .label = { spaces-toolbar-button-address-book.title } +spaces-pinned-button-menuitem-calendar = + .label = { spaces-toolbar-button-calendar.title } +spaces-pinned-button-menuitem-tasks = + .label = { spaces-toolbar-button-tasks.title } +spaces-pinned-button-menuitem-chat = + .label = { spaces-toolbar-button-chat.title } +spaces-pinned-button-menuitem-reveal = + .label = { spaces-toolbar-button-reveal.title } +# Variables: +# $count (Number) - Number of unread messages. +chat-button-unread-messages = { $count } + .title = + { $count -> + [one] Egy olvasatlan üzenet + *[other] { $count } olvasatlan üzenet + } + +## Spaces toolbar customize panel + +spaces-context-customize = + .label = Testreszabás… +spaces-customize-panel-title = Helyek eszköztár beállításai +spaces-customize-background-color = Háttérszín +spaces-customize-icon-color = Gomb színe +# The background color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-background-color = Kiválasztott gomb háttérszíne +# The icon color used on the buttons of the spaces toolbar when they are +# `current`, meaning the related space/tab is active and visible. +spaces-customize-accent-text-color = Kiválasztott gomb színe +spaces-customize-button-restore = Alapértelmezések helyreállítása + .accesskey = h +spaces-customize-button-save = Kész + .accesskey = K diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/openpgp/oneRecipientStatus.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/openpgp/oneRecipientStatus.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-03-07 21:38:48.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/openpgp/oneRecipientStatus.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -16,15 +16,13 @@ .label = Részletek megnyitása és elfogadás szerkesztése… openpgp-one-recipient-status-discover = .label = Új vagy frissített kulcs felfedezése - openpgp-one-recipient-status-instruction1 = Végpontok között titkosított üzenet adott címzetthez való küldéséhez meg kell szereznie annak OpenPGP nyilvános kulcsát, és elfogadottként kell megjelölnie. openpgp-one-recipient-status-instruction2 = A nyilvános kulcs megszerzéséhez importálja őket egy olyan e-mailből, amelyet Önnek küldtek, és tartalmazza azt. Alternatív megoldásként megpróbálhatja felfedezni a nyilvános kulcsot egy címtárban. - openpgp-key-own = Elfogadva (személyes kulcs) openpgp-key-secret-not-personal = Nem használható openpgp-key-verified = Elfogadva (ellenőrzött) openpgp-key-unverified = Elfogadva (nem ellenőrzött) openpgp-key-undecided = Nincs elfogadva (eldöntetlen) openpgp-key-rejected = Nincs elfogadva (elutasított) - +openpgp-key-expired = Lejárt openpgp-intro = Elérhető nyilvános kulcsok ehhez: { $key } diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/otr/add-finger.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/otr/add-finger.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/otr/add-finger.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/otr/add-finger.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -4,14 +4,12 @@ otr-add-finger = .title = OTR-kulcs ujjlenyomatának hozzáadása - +otr-add-finger-title = OTR-kulcs ujjlenyomatának hozzáadása # Variables: # $name (String) - name of a chat contact person # Do not translate 'OTR' (name of an encryption protocol) otr-add-finger-description = Adja meg a OTR-kulcs ujjlenyomatát { $name } számára. - otr-add-finger-fingerprint = Ujjlenyomat: otr-add-finger-tooltip-error = Érvénytelen karaktert írt be. Csak az ABCDEF betűk és a számok megengedettek. - otr-add-finger-input = .placeholder = Az OTR-kulcs 40 karakter hosszú ujjlenyomata diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/otr/finger.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/otr/finger.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/otr/finger.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/otr/finger.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -5,18 +5,15 @@ otr-finger = .buttonlabelaccept = Bezárás .title = Előzőleg látott OTR-ujjlenyomatok - +otr-finger-title = Korábban látott OTR ujjlenyomatok finger-intro = Az OTR-kulcs ujjlenyomatai a korábbi, végpontok között titkosított beszélgetésekből. - finger-screen-name = .label = Kapcsolat finger-verified = .label = Ellenőrzési állapot finger-fingerprint = .label = Ujjlenyomat - finger-remove = .label = Kijelölt eltávolítása - finger-remove-all = .label = Összes eltávolítása diff -Nru thunderbird-91.7.0+build2/l10n/hu/mail/messenger/preferences/preferences.ftl thunderbird-91.8.1+build1/l10n/hu/mail/messenger/preferences/preferences.ftl --- thunderbird-91.7.0+build2/l10n/hu/mail/messenger/preferences/preferences.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/mail/messenger/preferences/preferences.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -193,6 +193,9 @@ smooth-scrolling-label = .label = Finom görgetés .accesskey = F +browsing-gtk-use-non-overlay-scrollbars = + .label = Mindig jelenítse meg a görgetősávokat + .accesskey = g system-integration-legend = Integrálódás a rendszerbe always-check-default = .label = Indításkor ellenőrzés, hogy a { -brand-short-name }-e az alapértelmezett levelező diff -Nru thunderbird-91.7.0+build2/l10n/hu/toolkit/chrome/global/aboutReader.properties thunderbird-91.8.1+build1/l10n/hu/toolkit/chrome/global/aboutReader.properties --- thunderbird-91.7.0+build2/l10n/hu/toolkit/chrome/global/aboutReader.properties 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/toolkit/chrome/global/aboutReader.properties 2022-04-15 07:53:50.000000000 +0000 @@ -35,7 +35,7 @@ aboutReader.fontType.sans-serif=Talpatlan # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types. -# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 +# For followup see: https://bugzilla.mozilla.org/show_bug.cgi?id=1637089 aboutReader.fontTypeSample=Aa aboutReader.toolbar.close=Olvasó nézet bezárása @@ -64,3 +64,4 @@ aboutReader.toolbar.colorschemelight = Világos színséma aboutReader.toolbar.colorschemedark = Sötét színséma aboutReader.toolbar.colorschemesepia = Szépia színséma +aboutReader.toolbar.colorschemeauto = Automatikus színséma diff -Nru thunderbird-91.7.0+build2/l10n/hu/toolkit/chrome/global/narrate.properties thunderbird-91.8.1+build1/l10n/hu/toolkit/chrome/global/narrate.properties --- thunderbird-91.7.0+build2/l10n/hu/toolkit/chrome/global/narrate.properties 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/toolkit/chrome/global/narrate.properties 2022-04-15 07:53:50.000000000 +0000 @@ -2,13 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# "Listen, which allows users to listen to Firefox reading the text, +# "Listen, which allows users to listen to Firefox reading the text, # instead of having to read it themselves." This is the name # of the feature and it is the label for the popup button. listen = Figyeljen back = Vissza start = Kezdés stop = Leállítás +# %S is the keyboard shortcut for the start command +start-label = Indítás (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Leállítás (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Előre speed = Sebesség selectvoicelabel = Hang: diff -Nru thunderbird-91.7.0+build2/l10n/hu/toolkit/toolkit/about/aboutMozilla.ftl thunderbird-91.8.1+build1/l10n/hu/toolkit/toolkit/about/aboutMozilla.ftl --- thunderbird-91.7.0+build2/l10n/hu/toolkit/toolkit/about/aboutMozilla.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/toolkit/toolkit/about/aboutMozilla.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -4,8 +4,7 @@ about-mozilla-title-6-27 = Mozilla könyve, 6:27 about-mozilla-quote-6-27 = - A Fenevad megújult Fókusszal folytatta tanulmányait, nagyszerű Referenciamunkákat - készítve és új Valóságokat fontolgatva. A Fenevad előhozta követőit és - tanítványait, hogy saját maga megújult, kisebb formáját hozza létre, és Csintalan módokon - elküldte az egész világnak. + A Fenevad megújult Fókusszal folytatta tanulmányait, pompázatos Mestermunkákat + készítvén és új Valóságokat fontolgatva. A Fenevad előhozta követőit és + tanítványait, hogy önnönmaga megújult, délceg formáját hozza létre, és Csintalan módszerekkel elküldé az egész világnak. about-mozilla-from-6-27 = Mozilla könyve, 6:27 diff -Nru thunderbird-91.7.0+build2/l10n/hu/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/hu/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/hu/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -185,6 +185,22 @@ ## +# This is the total number of frames encoded or decoded over an RTP stream. +# Variables: +# $frames (Number) - The number of frames encoded or decoded. +about-webrtc-frames = + { $frames -> + [one] { $frames } képkocka + *[other] { $frames } képkocka + } +# This is the number of audio channels encoded or decoded over an RTP stream. +# Variables: +# $channels (Number) - The number of channels encoded or decoded. +about-webrtc-channels = + { $channels -> + [one] { $channels } csatorna + *[other] { $channels } csatorna + } # This is the total number of packets received on the PeerConnection. # Variables: # $packets (Number) - The number of packets received. diff -Nru thunderbird-91.7.0+build2/l10n/hu/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/hu/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/hu/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:38:49.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hu/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:53:50.000000000 +0000 @@ -94,3 +94,7 @@ experimental-features-ime-search = .label = Címsor: az eredmények megjelenítése az IME összeállítása alatt experimental-features-ime-search-description = Az IME (bemenetimód-szerkesztő) egy olyan eszköz, amellyel összetett szimbólumokat írhat be szabványos billentyűzetről, például olyanokat, melyek kelet-ázsiai vagy indoárja írt nyelvekben használatosak. A kísérlet engedélyezésével a címsáv panel nyitva marad, és keresési találatok és javaslatokat fog kapni, ha szövegbevitelre használja az IME-t. Ne feledje, hogy az IME olyan panelt jeleníthet meg, amely lefedi a címsáv találatait, ezért ez a beállítás csak akkor javasolt, ha nem ezt a típusú panelt használja. +# Firefox 100 +experimental-features-firefox-100 = + .label = { -brand-product-name } 100 User-Agent karakterlánc +experimental-features-firefox-100-description = A { -brand-short-name } olyan User-Agent karakterláncot küld a weboldalaknak, amely alapján a { -brand-product-name } 100-as verziójának tűnik. Ezt a beállítást arra használhatja, hogy tesztelje a weboldalakat, hogy elromlanak-e, ha a { -brand-short-name } eléri a három jegyű verziószámot. A valódi { -brand-product-name } 100 ütemterv szerint 2022 májusában jelenik meg, így kezdje el a tesztelést még most! diff -Nru thunderbird-91.7.0+build2/l10n/hy-AM/chat/imtooltip.properties thunderbird-91.8.1+build1/l10n/hy-AM/chat/imtooltip.properties --- thunderbird-91.7.0+build2/l10n/hy-AM/chat/imtooltip.properties 2022-03-07 21:38:55.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hy-AM/chat/imtooltip.properties 2022-04-15 07:53:57.000000000 +0000 @@ -7,4 +7,6 @@ contact.tags=Պիտակներ otr.tag=OTR վիճակներ + +encryption.tag=Գաղտնագրման վիճակը message.status=Հաղորդագրությունը գատնագրված է diff -Nru thunderbird-91.7.0+build2/l10n/hy-AM/chat/matrix.properties thunderbird-91.8.1+build1/l10n/hy-AM/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/hy-AM/chat/matrix.properties 2022-03-07 21:38:55.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hy-AM/chat/matrix.properties 2022-04-15 07:53:57.000000000 +0000 @@ -6,10 +6,12 @@ # This is displayed inside the accountUsernameInfoWithDescription # string defined in imAccounts.properties when the user is # configuring a Matrix account. +matrix.usernameHint=Մատրիցայի ID # LOCALIZATION NOTE (options.*): # These are the protocol specific options shown in the account manager and # account wizard windows. +options.saveToken=Խանութ մուտք գործելու կտրոն options.homeserver=Սպասարկիչ @@ -17,6 +19,9 @@ # These are strings used to build the status information of the encryption # storage, shown in the account manager. %S is one of the statuses and the # strings are combined with a pipe (|) between. +options.encryption.secretStorage=Գաղտնի պահեստ. %S +options.encryption.crossSigning=Խաչաձեւ ստորագրութիւն․ %S +options.encryption.statusOk=լավ options.encryption.statusNotOk=պատրաստ չէ # %1$S is the session ID, %2$S is the session display name options.encryption.session=%1$S (%2$S) @@ -53,6 +58,8 @@ # LOCALIZATION NOTE (powerLevel.*): # These are the string representations of different standard power levels and strings. # %S are one of the power levels, Default/Moderator/Admin/Restricted/Custom. +powerLevel.default=Լռելյայն +powerLevel.custom=Հարմարեցված # %1$S is the power level name # %2$S is the power level number diff -Nru thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/addons.properties thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/addons.properties --- thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/addons.properties 2022-03-07 21:38:55.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/addons.properties 2022-04-15 07:53:57.000000000 +0000 @@ -35,6 +35,10 @@ # the administration can add to the message. addonInstallBlockedByPolicy=%1$S(%2$S)-ը արգելափակված է Ձեր համակարգավարի կողմից։ %3$S +# LOCALIZATION NOTE (addonPostInstall.message2) +# %S is replaced with the localized named of the extension that was +# just installed. + # LOCALIZATION NOTE (addonDownloadingAndVerifying): # Semicolon-separated list of plural forms. See: # http://developer.mozilla.org/en/docs/Localization_and_Plurals @@ -92,17 +96,17 @@ # LOCALIZATION NOTE (addonInstallErrorBlocklisted): %S is add-on name addonInstallErrorBlocklisted=%S-ը չի կարող տեղադրվել, քանի որ այն պարունակում է անվտանգության խնդիրներ: -# LOCALIZATION NOTE (webextPerms.header) -# This string is used as a header in the webextension permissions dialog, +# LOCALIZATION NOTE (webextPerms.header,webextPerms.headerWithPerms,webextPerms.headerUnsigned,webextPerms.headerUnsignedWithPerms) +# These strings are used as headers in the webextension permissions dialog, # %S is replaced with the localized name of the extension being installed. # See https://bug1308309.bmoattachments.org/attachment.cgi?id=8814612 # for an example of the full dialog. -# Note, this string will be used as raw markup. Avoid characters like <, >, & +# Note, these strings will be used as raw markup. Avoid characters like <, >, & webextPerms.header=Ավելացնե՞լ %S-ը # %S is brandShortName webextPerms.experimentWarning=Զգուշացում. Այս հավելումը վավերացված չէ: Վնասագիր հավելումները կարող են գողանալ ձեր անձնական տեղեկությունները կամ վնասեն ձեր համակարգիչը: Տեղադրեք այն, եթե միայն վստահում եք աղբյուրին: - +webextPerms.learnMore2=Իմանալ ավելին webextPerms.add.label=Ավելացնել webextPerms.add.accessKey=A webextPerms.cancel.label=Չեղարկել @@ -132,6 +136,10 @@ # has been updated. webextPerms.updateMenuItem=%S-ը պահանջում է նոր թույլտվություններ +# LOCALIZATION NOTE (webextPerms.updateText2) +# %S is replaced with the localized name of the updated extension. +# Note, this string will be used as raw markup. Avoid characters like <, >, & + webextPerms.updateAccept.label=Թարմացնել webextPerms.updateAccept.accessKey=U @@ -206,6 +214,14 @@ # hosts for which this webextension is requesting permission. webextPerms.hostDescription.tooManySites=Մատչել ձեր տվյալներին #1 այլ կայքում;Մատչել ձեր տվյալներին #1 այլ կայքերում +# LOCALIZATION NOTE (webextSitePerms.headerWithPerms,webextSitePerms.headerUnsignedWithPerms) +# This string is used as a header in the webextension permissions dialog, +# %1$S is replaced with the localized name of the extension being installed. +# %2$S will be replaced by the DNS host name for which a webextension enables permissions +# Note, this string will be used as raw markup. Avoid characters like <, >, & + +# These should remain in sync with permissions.NAME.label in sitePermissions.properties + # LOCALIZATION NOTE (webext.defaultSearch.description) # %1$S is replaced with the localized named of the extension that is asking to change the default search engine. # %2$S is replaced with the name of the current search engine @@ -215,4 +231,3 @@ webext.defaultSearchYes.accessKey=Y webext.defaultSearchNo.label=Ոչ webext.defaultSearchNo.accessKey=N - diff -Nru thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/messenger.dtd thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/messenger.dtd --- thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/messenger.dtd 2022-03-07 21:38:55.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/messenger.dtd 2022-04-15 07:53:57.000000000 +0000 @@ -490,6 +490,7 @@ + diff -Nru thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/messenger.properties thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/messenger.properties --- thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/messenger.properties 2022-03-07 21:38:55.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/messenger.properties 2022-04-15 07:53:57.000000000 +0000 @@ -688,6 +688,8 @@ lwthemePostInstallNotification.manageButton=Թեմաների կառավարում… lwthemePostInstallNotification.manageButton.accesskey=Թ +# troubleshootModeRestart + # LOCALIZATION NOTE (downloadAndInstallButton.label): %S is replaced by the # version of the update: "Update to 28.0". update.downloadAndInstallButton.label=Թարմացնել %S-ի @@ -751,6 +753,11 @@ # LOCALIZATION NOTE (panel.back): # This is used by screen readers to label the "back" button in various browser -# popup panels, including the sliding subviews of the appmenu. +# popup panels, including the sliding subviews of the appmenu. panel.back = Հետ +# LOCALIZATION NOTE (folderErrorAlertTitle): +# %S is a pretty string to identify the folder and account. +# EXAMPLE: Error - Inbox on bob@example.com +folderErrorAlertTitle = Սխալ. %S + diff -Nru thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/migration/migration.properties thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/migration/migration.properties --- thunderbird-91.7.0+build2/l10n/hy-AM/mail/chrome/messenger/migration/migration.properties 2022-03-07 21:38:55.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hy-AM/mail/chrome/messenger/migration/migration.properties 2022-04-15 07:53:57.000000000 +0000 @@ -14,6 +14,7 @@ 2_outlook=Փոստարկղի կարգավորումներ 4_seamonkey=Հասցեագրքեր +4_thunderbird=Հասցեագիրք 4_outlook=Հասցեագիրք 8_seamonkey=Փոստաղբ նամակի ուսուցում diff -Nru thunderbird-91.7.0+build2/l10n/hy-AM/toolkit/toolkit/about/aboutAddons.ftl thunderbird-91.8.1+build1/l10n/hy-AM/toolkit/toolkit/about/aboutAddons.ftl --- thunderbird-91.7.0+build2/l10n/hy-AM/toolkit/toolkit/about/aboutAddons.ftl 2022-03-07 21:38:55.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/hy-AM/toolkit/toolkit/about/aboutAddons.ftl 2022-04-15 07:53:57.000000000 +0000 @@ -3,103 +3,74 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. addons-page-title = Հավելումների կառավարում - search-header = .placeholder = Որոնել addons.mozilla.org֊ում .searchbuttonlabel = Որոնել addons.mozilla.org֊ում - search-header-shortcut = .key = f - list-empty-installed = .value = Դուք չունեք տեղակայված այս տեսակի հավելումներ - list-empty-available-updates = .value = Թարմացում չի գտնվել - list-empty-recent-updates = .value = Վերջին ժամանակներում դուք չեք թարմացրել որևէ հավելում - list-empty-find-updates = .label = Ստուգվում է թարմացումները - list-empty-button = .label = Կարդալ հավելումների մասին - help-button = Լրացուցիչ աջակցություն sidebar-help-button-title = .title = Լրացուցիչ աջակցություն - show-unsigned-extensions-button = .label = Որոշ ընդլայնումներ չեն կարող ստուգվել: - show-all-extensions-button = .label = Ցուցադրել բոլորը - detail-version = .label = Տարբերակ - detail-last-updated = .label = Վերջին Թարմացումը - detail-contributions-description = Այս հավելման ստեղծողը խնդրում է, որ դուք աջակցեք հավելման զարգացմանը` կատարելով փոքր ներդրում: - detail-contributions-button = Աջակցել .title = Աջակցել այս հավելասարքի մշակմանը .accesskey = C - detail-update-type = .value = Ինքնաշխատ Թարմացումներ - detail-update-default = .label = Լռելյայն .tooltiptext = Ինքնաբար տեղադրել թարմացումները, եթե միայն սա լռելյայն է - detail-update-automatic = .label = Միացնել .tooltiptext = Տեղադրել թարմացումները ինքնաբար: - detail-update-manual = .label = Անջատել .tooltiptext = Չտեղադրել թարմացումները ինքնաբար - # Used as a description for the option to allow or block an add-on in private windows. detail-private-browsing-label = Սկսել Գաղտնի դիտարկում - # Some add-ons may elect to not run in private windows by setting incognito: not_allowed in the manifest. This # cannot be overridden by the user. detail-private-disallowed-label = Թույլատրված չէ անձնական պատուհանում detail-private-disallowed-description2 = Այս ընդլայնումը չի գործի անձնական զննարկման ժամանակ։ Իմանալ ավելին - # Some special add-ons are privileged, run in private windows automatically, and this permission can't be revoked detail-private-required-label = Պահանջվում է մուտք դեպի անձնական պատուհան detail-private-required-description2 = Այս ընդլայնումը հասանելի է ձեր առցանց գործունության՝ անձնական զննարկման ժամանակ։ Իմանալ ավելին - detail-private-browsing-on = .label = Թույլատրել .tooltiptext = Թույլատրել - detail-private-browsing-off = .label = Չթույլատրել .tooltiptext = Չթույլատրել - detail-home = .label = Կայքէջը - detail-home-value = .value = { detail-home.label } - detail-repository = .label = Հավելումների պռոֆիլ - detail-repository-value = .value = { detail-repository.label } - detail-check-for-updates = .label = Ստուգել թարմացումները .accesskey = Ս .tooltiptext = Ստուգել այս հավելման թարմացումների առկայությունը - detail-show-preferences = .label = { PLATFORM() -> @@ -116,38 +87,26 @@ [windows] Կարգավորել այս հավելումը *[other] Փոփոխել այս հավելման նախընտրանքները } - detail-rating = .value = Վարկանիշ - addon-restart-now = .label = Վերամեկնարկել հիմա - disabled-unsigned-heading = .value = Որոշ հավելումներ անջատվել են - disabled-unsigned-description = Հետևյալ հավելումները չեն ստուգվել { -brand-short-name }-ում: Դուք կարող եք կամ խնդրեք ստեղծողին ստուգել դրանք: - disabled-unsigned-learn-more = Իմանալ ավելին, թե ինչպես ենք մենք ապահովում Ձեր անվտանգությունը առցանց: - disabled-unsigned-devinfo = Ովքեր շահագրգռված են, որ իրենց հավելումները ստուգվեն, կարող են կարդալ մեր . - plugin-deprecation-description = Ինչ-որ բան բացակայու՞մ է: Որոշ բաղադրիչներ այլևս չեն աջակցվում { -brand-short-name }-ի կողմից: - legacy-warning-show-legacy = Ցուցադրել հնացած ընդլայնումները - legacy-extensions = .value = Հնացած ընդլայնումներ - legacy-extensions-description = Այս ընդլայնումները չեն համապատասխանում { -brand-short-name }-ի պահանջներին և ապաակտիվացվել են: - private-browsing-description2 = { -brand-short-name }-ը փոփոխում է ընդլայնման աշխատանքը անձնական զննարկամն ժամանակ։ Ցանկցած ձեր հավելած նոր ընդլայնումներ { -brand-short-name }-ը լռելյայն չի գործարկի Անձնական Պատուհաններում։ Մինչև կարգավորումներում թույլատրեք այն, ընդլայնումը չի աշխատի՝ անձնակնա զննարկմն ժամանակ և ձեր առցանց գործունության ժամանակ հասանելիության չի ունենա։ Մենք կատարել ենք այս փոփոխությունները ձեր անձնկան զննարկումը գաղտնի դարձնելու համար։ - addon-category-discover = Խորհուրդներ addon-category-discover-title = .title = Խորհուրդներ @@ -183,7 +142,6 @@ extensions-warning-update-security-button = Միացնել .title = Միացնել հավելման թարմացման անվտանգության ստուգումը - ## Strings connected to add-on updates addon-updates-check-for-updates = Ստուգել թարմացումները @@ -229,43 +187,34 @@ # This is displayed in the page options menu addon-manage-extensions-shortcuts = Ընդլայնման դյուրանցումների կառավարում .accesskey = S - shortcuts-no-addons = Դուք որևէ ընդլայնման միացված չեք։ shortcuts-no-commands = Հետևյալ ընդարձակումը չունի դյուրանցումներ․ shortcuts-input = .placeholder = Մուտքագրեք դյուրացնում - shortcuts-browserAction2 = Ակտիվացնել գործիքագոտու կոճակը shortcuts-pageAction = Ակտիվացրեք էջի գործողությունը shortcuts-sidebarAction = Բացել/Փակել կողային վահանակը - shortcuts-modifier-mac = Ներառել Ctrl, Alt, կամ ⌘ shortcuts-modifier-other = Ներառեք Ctrl կամ Alt shortcuts-invalid = Անվավեր համադրություն shortcuts-letter = Գրել նամակ shortcuts-system = Հնարավոր չէ անտեսել { -brand-short-name } կարճ դյուրանցում - # String displayed in warning label when there is a duplicate shortcut shortcuts-duplicate = Կրկնօրինակել դյուրացնում - # String displayed when a keyboard shortcut is already assigned to more than one add-on # Variables: # $shortcut (string) - Shortcut string for the add-on shortcuts-duplicate-warning-message = { $shortcut }-ը մեկից ավելի անգամ օգտագործվում է որպես դյուրանցում։ Կրկնօրինակված դյուրանցումները կարող են անսպասելի վարքի պատճառ դառնալ։ - # String displayed when a keyboard shortcut is already used by another add-on # Variables: # $addon (string) - Name of the add-on shortcuts-exists = Արդեն օգտագործվում է{ $addon } - shortcuts-card-expand-button = { $numberToShow -> [one] Ցույց տալ { $numberToShow } Ավելին *[other] Ցույց տալ { $numberToShow } Ավելին } - shortcuts-card-collapse-button = Ավելի քիչ - header-back-button = .title = Գնալ ետ @@ -278,15 +227,12 @@ պաշտպանել գաղտնաբառերը, ներբեռնել տեսանյութեր, գտնել գործարքներ, արգելափակել նյարդայնացնող գովազդները, փոխել ձեր զննարկչի տեսքը և ավելին։ Այս փոքր ծրագրային ծրագրերը հաճախ զարգացվել են երրորդ կողմի կողմից։ Ահա ընտրանք { -brand-product-name } - խորհուր է տրվում բացառիկ + խորհուրդ է տրվում բացառիկ անվտանգության, արդյունավետության և գործառություն համար։ - # Notice to make user aware that the recommendations are personalized. discopane-notice-recommendations = Այս առաջարկներից մի քանիսը անհատականացված են։ Դրանք հիմնված են ուրիշների վրա ձեր սահմանած ընդարձակումների, հատկագրի կարգավորումների և օգտագործման վիճակագրությունից։ discopane-notice-learn-more = Իմանալ ավելին - privacy-policy = Գաղտնիության դրույթներ - # Refers to the author of an add-on, shown below the name of the add-on. # Variables: # $author (string) - The name of the add-on developer. @@ -301,7 +247,6 @@ # the detailed add-on view is opened, from where the add-on can be managed. manage-addon-button = Կառավարել find-more-addons = Գտեք ավելի շատ հավելումներ - # This is a label for the button to open the "more options" menu, it is only # used for screen readers. addon-options-button = @@ -327,42 +272,32 @@ details-addon-button = Մանրամասներ release-notes-addon-button = Թողարկման նշումներ permissions-addon-button = Թույլտվություններ - extension-enabled-heading = Միացված extension-disabled-heading = Անջատված - theme-enabled-heading = Միացված theme-disabled-heading = Անջատված - plugin-enabled-heading = Միացված plugin-disabled-heading = Անջատված - dictionary-enabled-heading = Միացված dictionary-disabled-heading = Անջատված - locale-enabled-heading = Միացված locale-disabled-heading = Անջատված - always-activate-button = Միշտ ակտիվացնել never-activate-button = Երբեք չակտիվացնել - addon-detail-author-label = Հեղինակ addon-detail-version-label = Տարբերակ addon-detail-last-updated-label = Վերջին թարմացումը addon-detail-homepage-label = Կայքէջ addon-detail-rating-label = Վարկանիշ - # The average rating that the add-on has received. # Variables: # $rating (number) - A number between 0 and 5. The translation should show at most one digit after the comma. five-star-rating = .title = Գնահատված է { NUMBER($rating, maximumFractionDigits: 1) }՝ 5-ից - # This string is used to show that an add-on is disabled. # Variables: # $name (string) - The name of the add-on addon-name-disabled = { $name } (անջատված) - # The number of reviews that an add-on has received on AMO. # Variables: # $numberOfReviews (number) - The number of reviews received @@ -378,14 +313,12 @@ # $addon (string) - Name of the add-on pending-uninstall-description = { $addon }-ը հեռացվել է։ pending-uninstall-undo-button = Հետարկել - addon-detail-updates-label = Թույլատրել ինքնաթարմացումները addon-detail-updates-radio-default = Լռելյայն addon-detail-updates-radio-on = Միացնել addon-detail-updates-radio-off = Անջատել addon-detail-update-check-label = Ստուգել թարմացումները install-update-button = Թարմացնել - # This is the tooltip text for the private browsing badge in about:addons. The # badge is the private browsing icon included next to the extension's name. addon-badge-private-browsing-allowed2 = @@ -406,15 +339,11 @@ available-updates-heading = Առկա թարմացումներ recent-updates-heading = Վերջին թարմացումները - release-notes-loading = Բեռնում․․․ release-notes-error = Հնարավոր չեղավ բացել թողարկման նշումները։ - addon-permissions-empty = Այս ընդլայնումը չի պահանջում որևէ թույլատվություններ - recommended-extensions-heading = Երաշխավորված ընդլայնում recommended-themes-heading = Երաշխավորված հիմնապատկերներ - # A recommendation for the Firefox Color theme shown at the bottom of the theme # list view. The "Firefox Color" name itself should not be translated. recommended-theme-1 = Զգու՞մ եք ստեղծող։ Firefox Color-ով կառուցեք ձեր սեփական հիմնապատեկերը։ @@ -429,10 +358,8 @@ updates-heading = Կառավարեք ձեր թարմացումները discover-heading = Անհատականացրեք ձեր { -brand-short-name }-ը shortcuts-heading = Կառավարել ընդլայնման դյուրացումները - default-heading-search-label = Ավելի շատ հավելումներ addons-heading-search-input = .placeholder = Որոնել addons.mozilla.org֊-ում - addon-page-options-button = .title = Գործիքներ բոլոր հավելումների համար diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/compatibility.ftl thunderbird-91.8.1+build1/l10n/id/devtools/client/compatibility.ftl --- thunderbird-91.7.0+build2/l10n/id/devtools/client/compatibility.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/compatibility.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -41,7 +41,14 @@ { $number -> *[other] { $number } kemunculan } - compatibility-no-issues-found = Tidak ditemukan masalah kompatibilitas. compatibility-close-settings-button = .title = Pengaturan tertutup +# Text used in the element containing the browser icons for a given compatibility issue. +# Line breaks are significant. +# Variables: +# $browsers (String) - A line-separated list of browser information (e.g. Firefox 98\nChrome 99). +compatibility-issue-browsers-list = + .title = + Masalah kompatibilitas di: + { $browsers } diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/components.properties thunderbird-91.8.1+build1/l10n/id/devtools/client/components.properties --- thunderbird-91.7.0+build2/l10n/id/devtools/client/components.properties 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/components.properties 2022-04-15 07:54:04.000000000 +0000 @@ -22,3 +22,16 @@ # LOCALIZATION NOTE (notificationBox.closeTooltip): The content of a tooltip that # appears when hovering over the close button in a notification box. notificationBox.closeTooltip=Tutup pesan ini + +# LOCALIZATION NOTE (appErrorBoundary.description): This is the information displayed +# once the panel errors. +# %S represents the name of panel which has the crash. +appErrorBoundary.description=Panel %S mogok. + +# LOCALIZATION NOTE (appErrorBoundary.fileBugButton): This is the text that appears in +# the button to visit the bug filing link. +appErrorBoundary.fileBugButton=Kirimkan Laporan Bug + +# LOCALIZATION NOTE (appErrorBoundary.reloadPanelInfo): This is the text that appears +# after the panel errors to instruct the user to reload the panel. +appErrorBoundary.reloadPanelInfo=Tutup dan buka kembali kotak alat untuk membersihkan kesalahan ini. diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/id/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/id/devtools/client/debugger.properties 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/debugger.properties 2022-04-15 07:54:04.000000000 +0000 @@ -642,6 +642,26 @@ ignoreContextItem.unignore=Batalkan mengabaikan sumber ignoreContextItem.unignore.accesskey=s +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item +ignoreContextItem.ignoreLine=Abaikan baris +ignoreContextItem.ignoreLine.accesskey=A + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item +ignoreContextItem.unignoreLine=Jangan abaikan baris +ignoreContextItem.unignoreLine.accesskey=J + +# LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated +# with the ignore lines context menu item +ignoreContextItem.ignoreLines=Abaikan baris +ignoreContextItem.ignoreLines.accesskey=A + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLines): Text associated +# with the unignore lines context menu item +ignoreContextItem.unignoreLines=Jangan abaikan baris +ignoreContextItem.unignoreLines.accesskey=J + # LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated # with a mapped source. %S is replaced by the source map origin. sourceFooter.mappedSource=(Dari %S) diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/id/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/id/devtools/client/netmonitor.properties 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/netmonitor.properties 2022-04-15 07:54:05.000000000 +0000 @@ -855,6 +855,10 @@ # in the action bar's search tab netmonitor.actionbar.search=Cari +# LOCALIZATION NOTE (netmonitor.actionbar.HTTPCustomRequest): This is the label displayed +# in the action bar's edit and resend tab +netmonitor.actionbar.HTTPCustomRequest=Permintaan Baru + # LOCALIZATION NOTE (messagesTruncated): This is the text displayed # in the messages panel when the number of messages is over the # truncation limit. @@ -1005,6 +1009,10 @@ # in the network toolbar for the search button. netmonitor.toolbar.search=Cari +# LOCALIZATION NOTE (netmonitor.toolbar.HTTPCustomRequest): This is the tooltip label displayed +# in the network toolbar for the new HTTP Custom Request button. +netmonitor.toolbar.HTTPCustomRequest=Permintaan Baru + # LOCALIZATION NOTE (netmonitor.toolbar.resetColumns): This is the label # displayed in the network table header context menu. netmonitor.toolbar.resetColumns=Setel Ulang Kolom @@ -1079,6 +1087,15 @@ # from the currently displayed request netmonitor.headers.raw=Mentah +# LOCALIZATION NOTE (netmonitor.headers.blockedByCORS): This is the message displayed +# in the notification shown when a request has been blocked by CORS with a more +# specific reason shown in the parenthesis +netmonitor.headers.blockedByCORS=Badan respons tidak tersedia untuk skrip (Alasan: %S) + +#LOCALIZATION NOTE (netmonitor.headers.blockedByCORSTooltip): This is the tooltip +# displayed on the learnmore link of the blocked by CORS notification. +netmonitor.headers.blockedByCORSTooltip=Pelajari lebih lanjut tentang kesalahan CORS ini + # LOCALIZATION NOTE (netmonitor.response.name): This is the label displayed # in the network details response tab identifying an image's file name or font face's name. netmonitor.response.name=Nama: @@ -1443,10 +1460,34 @@ # above the query string entry in the custom request form netmonitor.custom.query=String Kueri: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form +netmonitor.custom.urlParameters=Parameter URL + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Header Permintaan: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form +netmonitor.custom.newRequestHeaders=Header + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.name=nama + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form +netmonitor.custom.placeholder.value=nilai + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form +netmonitor.custom.postBody=Badan + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form +netmonitor.custom.postBody.placeholder=payload + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Isi Permintaan: @@ -1459,6 +1500,14 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Batal +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel +netmonitor.custom.clear=Bersihkan + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item +netmonitor.custom.removeItem=Hapus item + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Kembali diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/perftools.ftl thunderbird-91.8.1+build1/l10n/id/devtools/client/perftools.ftl --- thunderbird-91.7.0+build2/l10n/id/devtools/client/perftools.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/perftools.ftl 2022-04-15 07:54:05.000000000 +0000 @@ -41,9 +41,7 @@ # The size of the memory buffer used to store things in the profiler. perftools-range-entries-label = Ukuran buffer: - perftools-custom-threads-label = Tambahkan thread khusus berdasarkan nama: - perftools-devtools-interval-label = Interval: perftools-devtools-threads-label = Thread: perftools-devtools-settings-label = Pengaturan @@ -100,7 +98,6 @@ ## perftools-record-all-registered-threads = Lewati pilihan di atas dan rekam semua utas yang terdaftar - perftools-tools-threads-input-label = .title = Nama utas ini berupa daftar yang dipisahkan karakter koma, yang akan digunakan untuk mengaktifkan profiling utas pada profiler. Pencocokan nama juga akan dilakukan secara bagian, tidak secara lengkap pada utas yang disertakan. Karakter spasi pada nama berpengaruh. @@ -109,9 +106,29 @@ ## preferences are true. perftools-onboarding-message = Baru: { -profiler-brand-name } telah diintegrasikan ke dalam Alat Pengembang. Pelajari lebih lanjut tentang alat baru yang canggih ini. - # `options-context-advanced-settings` is defined in toolbox-options.ftl perftools-onboarding-reenable-old-panel = (Untuk waktu yang terbatas, Anda dapat mengakses panel Kinerja lawas melalui { options-context-advanced-settings }) - perftools-onboarding-close-button = .aria-label = Tutup pesan orientasi + +## Profiler presets + + +# Presets and their l10n IDs are defined in the file +# devtools/client/performance-new/popup/background.jsm.js +# The same labels and descriptions are also defined in appmenu.ftl. + +perftools-presets-web-developer-label = Pengembang Web +perftools-presets-web-developer-description = Prasetel yang direkomendasikan untuk sebagian besar debugging aplikasi web, dengan overhead yang rendah. +perftools-presets-firefox-label = { -brand-shorter-name } +perftools-presets-firefox-description = Prasetel yang disarankan untuk pembuatan profil { -brand-shorter-name }. +perftools-presets-graphics-label = Grafik +perftools-presets-graphics-description = Prasetel untuk menyelidiki bug grafis di { -brand-shorter-name }. +perftools-presets-media-label = Media +perftools-presets-media-description2 = Prasetel untuk menyelidiki bug audio dan video di { -brand-shorter-name }. +perftools-presets-networking-label = Jaringan +perftools-presets-networking-description = Prasetel untuk menyelidiki bug jaringan di { -brand-shorter-name }. +perftools-presets-custom-label = Khusus + +## + diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/toolbox.ftl thunderbird-91.8.1+build1/l10n/id/devtools/client/toolbox.ftl --- thunderbird-91.7.0+build2/l10n/id/devtools/client/toolbox.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/toolbox.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -24,6 +24,8 @@ # to stay visible on blur, which is primarily useful for addon developers and Firefox # contributors. toolbox-meatball-menu-noautohide-label = Nonaktifkan sembulan sembunyi otomatis +toolbox-meatball-menu-pseudo-locale-accented = Aktifkan pelokalan "beraksen" +toolbox-meatball-menu-pseudo-locale-bidi = Aktifkan pelokalan "bidi" ## diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/toolbox-options.ftl thunderbird-91.8.1+build1/l10n/id/devtools/client/toolbox-options.ftl --- thunderbird-91.7.0+build2/l10n/id/devtools/client/toolbox-options.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/toolbox-options.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -10,19 +10,15 @@ # The heading options-select-default-tools-label = Alat Pengembang Bawaan - # The label for the explanation of the * marker on a tool which is currently not supported # for the target of the toolbox. options-tool-not-supported-label = * Tidak didukung untuk target kotak alat saat ini - # The label for the heading of group of checkboxes corresponding to the developer tools # added by add-ons. This heading is hidden when there is no developer tool installed by add-ons. options-select-additional-tools-label = Alat Pengembang yang diinstal dari pengaya - # The label for the heading of group of checkboxes corresponding to the default developer # tool buttons. options-select-enabled-toolbox-buttons-label = Tombol Kotak Alat yang Tersedia - # The label for the heading of the radiobox corresponding to the theme options-select-dev-tools-theme-label = Tema @@ -30,12 +26,10 @@ # The heading options-context-inspector = Inspektur - # The label for the checkbox option to show user agent styles options-show-user-agent-styles-label = Tampilkan Gaya Peramban options-show-user-agent-styles-tooltip = .title = Jika opsi ini diaktifkan, gaya baku yang dimuat peramban akan ditampilkan. - # The label for the checkbox option to enable collapse attributes options-collapse-attrs-label = Potong atribut DOM options-collapse-attrs-tooltip = @@ -48,13 +42,13 @@ options-default-color-unit-hex = Heksa options-default-color-unit-hsl = HSL(A) options-default-color-unit-rgb = MHB(A) +options-default-color-unit-hwb = HWB options-default-color-unit-name = Nama Warna ## Style Editor section # The heading options-styleeditor-label = Editor Gaya - # The label for the checkbox that toggles autocompletion of css in the Style Editor options-stylesheet-autocompletion-label = CSS Lengkapi-Otomasis options-stylesheet-autocompletion-tooltip = @@ -64,12 +58,10 @@ # The heading options-screenshot-label = Perilaku Tangkapan Layar - # Label for the checkbox that toggles screenshot to clipboard feature options-screenshot-clipboard-only-label = Cuplikan layar ke papan klip saja options-screenshot-clipboard-tooltip2 = .title = Simpan tangkapan layar langsung ke papan klip - # Label for the checkbox that toggles the camera shutter audio for screenshot tool options-screenshot-audio-label = Bunyikan suara shutter kamera options-screenshot-audio-tooltip = @@ -79,7 +71,6 @@ # The heading options-sourceeditor-label = Pengaturan Editor - options-sourceeditor-detectindentation-tooltip = .title = Tebak indentasi berdasarkan isi kode sumber options-sourceeditor-detectindentation-label = Deteksi indentasi @@ -97,40 +88,36 @@ # The heading (this item is also used in perftools.ftl) options-context-advanced-settings = Setelan lanjutan - # The label for the checkbox that toggles the HTTP cache on or off options-disable-http-cache-label = Menonaktifkan HTTP Cache (saat kotak peralatan terbuka) options-disable-http-cache-tooltip = .title = Mengaktifkan opsi ini akan menonaktifkan cache HTTP untuk semua tab yang kotak peralatannya terbuka. Layanan Pekerja tidak terpengaruh oleh opsi ini. - # The label for checkbox that toggles JavaScript on or off options-disable-javascript-label = Nonaktifkan JavaScript * options-disable-javascript-tooltip = .title = Dengan mengaktifkan opsi ini, JavaScript pada tab sekarang akan dinonaktifkan. Jika tab atau kotak alat ditutup maka setelan ini akan dilupakan. - # The label for checkbox that toggles chrome debugging, i.e. the devtools.chrome.enabled preference options-enable-chrome-label = Aktifkan kotak alat debug chrome peramban dan pengaya options-enable-chrome-tooltip = .title = Mengaktifkan opsi ini akan dapat digunakan untuk menggunakan berbagai alat pengembang dalam konteks peramban (lewat Alat > Pengembang Web > Kotak Alat Peramban) serta mendebug pengaya dari Pengelola Pengaya - # The label for checkbox that toggles remote debugging, i.e. the devtools.debugger.remote-enabled preference options-enable-remote-label = Aktifkan pendebugan jarak jauh options-enable-remote-tooltip2 = .title = Mengaktifkan opsi ini akan memungkinkan untuk mendebug instans peramban ini dari jarak jauh - +# The label for checkbox that toggles custom formatters for objects +options-enable-custom-formatters-label = Aktifkan pemformat khusus +options-enable-custom-formatters-tooltip = + .title = Mengaktifkan opsi ini akan memungkinkan situs menentukan pemformat khusus untuk objek DOM # The label for checkbox that toggles the service workers testing over HTTP on or off. options-enable-service-workers-http-label = Aktifkan Service Worker lewat HTTP (saat kotak alat terbuka) options-enable-service-workers-http-tooltip = .title = Mengaktifkan opsi ini akan mengaktifkan Service Worker lewat HTTP untuk semua tab yang kotak alatnya terbuka. - # The label for the checkbox that toggles source maps in all tools. options-source-maps-label = Aktifkan Peta Sumber options-source-maps-tooltip = .title = Jika opsi ini diaktifkan, kode sumber akan dipetakan dalam alat. - # The message shown for settings that trigger page reload options-context-triggers-page-refresh = * Hanya sesi ini saja, memulai ulang laman - # The label for the checkbox that toggles the display of the platform data in the # Profiler i.e. devtools.profiler.ui.show-platform-data a boolean preference in about:config options-show-platform-data-label = Tampilkan data platform Gecko diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/toolbox.properties thunderbird-91.8.1+build1/l10n/id/devtools/client/toolbox.properties --- thunderbird-91.7.0+build2/l10n/id/devtools/client/toolbox.properties 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/toolbox.properties 2022-04-15 07:54:04.000000000 +0000 @@ -27,6 +27,10 @@ # toolbox as a whole toolbox.label=Perangkat Pengembang +# LOCALIZATION NOTE (options.autoTheme.label) +# Used as a label for auto theme +options.autoTheme.label=Otomatis + # LOCALIZATION NOTE (options.toolNotSupportedMarker): This is the template # used to add a * marker to the label for the Options Panel tool checkbox for the # tool which is not supported for the current toolbox target. @@ -43,6 +47,18 @@ # shortcuts: Cmd+Shift+C or Cmd+Opt+C toolbox.elementPicker.mac.tooltip=Pilih elemen dari laman (%1$S atau %2$S) +# LOCALIZATION NOTE (toolbox.androidElementPicker.tooltip) +# This is the tooltip of the element picker button in the about:devtools-toolbox toolbox toolbar +# when debugging an Android device +# %S is the keyboard shortcut that toggles the element picker. +toolbox.androidElementPicker.tooltip=Pilih elemen dari ponsel Android (%S) + +# LOCALIZATION NOTE (toolbox.androidElementPicker.mac.tooltip) +# Like toolbox.androidElementPicker.tooltip, but for macOS as there are two possible keyboard +# shortcuts (Cmd+Shift+C or Cmd+Opt+C) +# %1$S and %2$S are the keyboard shortcuts that toggle the element picker. +toolbox.androidElementPicker.mac.tooltip=Pilih elemen dari ponsel Android (%1$S atau %2$S) + # LOCALIZATION NOTE (toolbox.elementPicker.key) # Key shortcut used to toggle the element picker. toolbox.elementPicker.key=CmdOrCtrl+Shift+C @@ -70,6 +86,19 @@ toolbox.resumeOrderWarning=Laman tidak melanjutkan setelah debugger direkatkan. Untuk memperbaikinya, tutup dan buka lagi kotak alat. +# LOCALIZATION NOTE (toolbox.autoThemeNotification) +# Notification displayed in the toolbox notification box when the DevTools theme +# is set to auto and the user is using a dark Firefox theme. +# %S is the brand shorter name (eg Firefox) +toolbox.autoThemeNotification=DevTools sekarang mengikuti keseluruhan tema %S. Anda dapat kembali ke Tema Terang atau Gelap di panel Pengaturan. + +# LOCALIZATION NOTE (toolbox.autoThemeNotification.settingsButton) +# Text of the button displayed in the auto theme notification to open the settings +# panel. +# "Settings" refers to the name of the settings panel, and should most likely be +# the same as toolbox.meatballMenu.settings.label. +toolbox.autoThemeNotification.settingsButton=Buka Pengaturan + # LOCALIZATION NOTE (toolbox.help.key) # Key shortcut used to open the options panel toolbox.help.key=F1 @@ -84,7 +113,7 @@ # LOCALIZATION NOTE (toolbox.zoom*.key) # Key shortcuts used to zomm in/out or reset the toolbox -# Should match fullZoom*Cmd.commandkey values from browser.dtd +# Should match full-zoom-*-shortcut values from browserSets.ftl toolbox.zoomIn.key=CmdOrCtrl+Plus toolbox.zoomIn2.key=CmdOrCtrl+= @@ -209,6 +238,14 @@ # The version of runtime: %2$S toolbox.debugTargetInfo.runtimeLabel=%1$S (%2$S) +# LOCALIZATION NOTE (toolbox.debugTargetInfo.runtimeLabel.thisRuntime): this is displayed +# as a toolbox header in about:devtools-toolbox, when inspecting the current Firefox runtime +# (for instance, when inspecting one of its tabs in about:debugging) +# e.g. This Firefox (65.0a1) +# The name of the current runtime/application (brandShorterName): %1$S +# The version of runtime: %2$S +toolbox.debugTargetInfo.runtimeLabel.thisRuntime=%1$S ini (%2$S) + # LOCALIZATION NOTE (toolbox.debugTargetInfo.tabTitleRemote): # Used as the tab title for about:devtools-toolbox when connected to a remote target. # The connection type (see toolbox.debugTargetInfo.connection.*): %1$S @@ -277,3 +314,6 @@ # settings panel for the checkbox that enables the Multiprocess Browser Toolbox. options.enableMultiProcessToolbox=Aktifkan Kotak Alat Peramban Multiproses (harus memulai ulang Kotak Alat Peramban) +# LOCALIZATION NOTE (options.enableNewPerformancePanel): This is the text that appears in the +# settings panel for the checkbox that enables the new performance panel. +options.enableNewPerformancePanel=Aktifkan perekam kinerja baru (lalu buka kembali DevTools) diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/tooltips.ftl thunderbird-91.8.1+build1/l10n/id/devtools/client/tooltips.ftl --- thunderbird-91.7.0+build2/l10n/id/devtools/client/tooltips.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/tooltips.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -15,37 +15,21 @@ ## $display (string) - A CSS display value e.g. "inline-block". inactive-css-not-grid-or-flex-container = { $property } tidak berdampak pada elemen ini karena bukan kontainer flex atau kontainer grid. - inactive-css-not-grid-or-flex-container-or-multicol-container = { $property } tidak berdampak pada elemen ini karena bukan kontainer flex, atau kontainer grid, atau kontainer muli-kolom. - inactive-css-not-grid-or-flex-item = { $property } tidak berdampak pada elemen ini karena bukan grid atau item flex. - inactive-css-not-grid-item = { $property } tidak berdampak pada elemen ini karena bukan item grid. - inactive-css-not-grid-container = { $property } tidak berdampak pada elemen ini karena bukan kontainer grid. - inactive-css-not-flex-item = { $property } tidak berdampak pada elemen ini karena bukan item flex. - inactive-css-not-flex-container = { $property } tidak berdampak pada elemen ini karena bukan kontainer flex. - inactive-css-not-inline-or-tablecell = { $property } tidak berdampak pada elemen ini karena bukan elemen sebarus atau table-cell. - inactive-css-property-because-of-display = { $property } tidak berdampak pada elemen ini karena memiliki nilai display { $display }.. - inactive-css-not-display-block-on-floated = Nilai display telah diubah oleh mesin menjadi block karena elemennya mengambang. - inactive-css-property-is-impossible-to-override-in-visited = Tidak mungkin menimpa { $property } karena pembatasan :visited. - inactive-css-position-property-on-unpositioned-box = { $property } tidak berdampak pada elemen ini karena bukan elemen dengan posisi. - inactive-text-overflow-when-no-overflow = { $property } tidak berdampak pada elemen ini karena overflow:hidden tidak diatur. - inactive-css-not-for-internal-table-elements = { $property } tidak berpengaruh pada elemen tabel internal. - inactive-css-not-for-internal-table-elements-except-table-cells = { $property } tidak berpengaruh pada elemen tabel internal kecuali sel tabel. - inactive-css-not-table = { $property } tidak berpengaruh pada elemen ini karena bukan tabel. - inactive-scroll-padding-when-not-scroll-container = { $property } tidak berpengaruh pada elemen ini tidak menggulir. ## In the Rule View when a CSS property cannot be successfully applied we display @@ -53,37 +37,22 @@ ## the problem can be solved. inactive-css-not-grid-or-flex-container-fix = Coba tambahkan display:grid atau display:flex. { learn-more } - inactive-css-not-grid-or-flex-container-or-multicol-container-fix = Coba tambahkan baik display:grid, display:flex, maupun columns:2. { learn-more } - inactive-css-not-grid-or-flex-item-fix-2 = Coba tambahkan display:grid, display:flex, display:inline-grid, atau display:inline-flex. { learn-more } - +inactive-css-not-grid-or-flex-item-fix-3 = Coba tambahkan display:grid, display:flex, display:inline-grid, atau display:inline-flex ke induk elemen. { learn-more } inactive-css-not-grid-item-fix-2 = Coba tambahkan display:grid atau display:inline-grid pada induk elemen. { learn-more } - inactive-css-not-grid-container-fix = Coba tambahkan display:grid atau display:inline-grid. { learn-more } - inactive-css-not-flex-item-fix-2 = Coba tambahkan display:flex atau display:inline-flex pada induk elemen. { learn-more } - inactive-css-not-flex-container-fix = Coba tambahkan display:flex atau display:inline-flex. { learn-more } - inactive-css-not-inline-or-tablecell-fix = Coba tambahkan baik display:inline maupun display:table-cell. { learn-more } - inactive-css-non-replaced-inline-or-table-row-or-row-group-fix = Coba tambahkan baik display:inline-block maupun display:block. { learn-more } - inactive-css-non-replaced-inline-or-table-column-or-column-group-fix = Coba tambahkan display:inline-block. { learn-more } - inactive-css-not-display-block-on-floated-fix = Coba hapus float atau menambahkan display:block. { learn-more } - inactive-css-position-property-on-unpositioned-box-fix = Coba atur properti position menjadi selain static. { learn-more } - inactive-text-overflow-when-no-overflow-fix = Coba tambahkan overflow:hidden. { learn-more } - inactive-css-not-for-internal-table-elements-fix = Cobalah menyetel properti display-nya ke nilai lain selain table-cell, table-column, table-row, table-column-group, table-row-group, atau tabel-footer-group. { learn-more } - inactive-css-not-for-internal-table-elements-except-table-cells-fix = Cobalah menyetel properti display-nya ke nilai lain selain table-column, table-row, table-column-group, table-row-group, atau tabel-footer-group. { learn-more } - inactive-css-not-table-fix = Coba tambahkan display:table atau display:inline-table. { learn-more } - inactive-scroll-padding-when-not-scroll-container-fix = Coba tambahkan overflow:auto, overflow:scroll, atau overflow:hidden. { learn-more } ## In the Rule View when a CSS property may have compatibility issues with other browsers @@ -94,17 +63,10 @@ ## $rootProperty (string) - A raw CSS property name e.g. "user-select" that is not a platform specific alias. css-compatibility-default-message = { $property } tidak didukung pada peramban berikut: - css-compatibility-deprecated-experimental-message = { $property } adalah properti eksperimental yang sekarang tidak digunakan lagi oleh standard W3C. Properti ini tidak didukung di peramban berikut: - css-compatibility-deprecated-experimental-supported-message = { $property } adalah properti eksperimental yang sekarang tidak digunakan lagi oleh standard W3C. - css-compatibility-deprecated-message = { $property } adalah properti eksperimental yang sekarang tidak digunakan lagi oleh standard W3C. Properti ini tidak didukung di peramban berikut: - css-compatibility-deprecated-supported-message = { $property } adalah properti eksperimental yang sekarang tidak digunakan lagi oleh standard W3C. - css-compatibility-experimental-message = { $property } adalah properti eksperimental. Properti ini tidak didukung di peramban berikut: - css-compatibility-experimental-supported-message = { $property } adalah properti eksperimental. - css-compatibility-learn-more-message = Pelajari lebih lanjut tentang { $rootProperty } diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/client/webconsole.properties thunderbird-91.8.1+build1/l10n/id/devtools/client/webconsole.properties --- thunderbird-91.7.0+build2/l10n/id/devtools/client/webconsole.properties 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/client/webconsole.properties 2022-04-15 07:54:05.000000000 +0000 @@ -430,7 +430,18 @@ # Parameters: %S is the URL to file a bug about the error. webconsole.message.componentDidCatch.label=[DEVTOOLS ERROR] Kami mohon maaf, kami tidak dapat merender pesannya. Ini seharusnya tidak terjadi - harap laporkan bug di %S dengan metadata pesan dalam deskripsi. -# LOCALIZATION NOTE (webconsole.message.commands.blockedURL) +# LOCALIZATION NOTE (webconsole.message.commands.copyValueToClipboard) +# Label displayed when the string is copied to the clipboard as a result of a copy command, +# in the console, for example, copy({hello: "world"}). +webconsole.message.commands.copyValueToClipboard=String telah disalin ke papan klip. + +# LOCALIZATION NOTE (webconsole.error.commands.copyError): +# the error that is displayed when the "copy" command can't stringify an object +# "copy" should not be translated, because is a function name. +# Parameters: %S is the original error message +webconsole.error.commands.copyError=Perintah `copy` gagal, objek tidak dapat dijadikan string: %S + +# LOCALIZATION NOTE (webconsole.message.commands.blockedUR) # Label displayed when the :block command is successful # Parameters: %S is the URL filter webconsole.message.commands.blockedURL=Permintaan ke URL yang mengandung "%S" kini diblokir diff -Nru thunderbird-91.7.0+build2/l10n/id/devtools/shared/highlighters.ftl thunderbird-91.8.1+build1/l10n/id/devtools/shared/highlighters.ftl --- thunderbird-91.7.0+build2/l10n/id/devtools/shared/highlighters.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/devtools/shared/highlighters.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -31,3 +31,18 @@ # The layout type of an element shown in the infobar when hovering over a DOM element and # it is both a flex container and a flex item. flextype-dual = Kontainer Flex /Item +# The message displayed in the content page when the user clicks on the +# "Pick an element from the page" in about:devtools-toolbox inspector panel, when +# debugging a remote page. +# Variables +# $action (string) - Will either be remote-node-picker-notice-action-desktop or +# remote-node-picker-notice-action-touch +remote-node-picker-notice = Pemilih Simpul DevTools diaktifkan. { $action } +# Text displayed in `remote-node-picker-notice`, when the remote page is on desktop +remote-node-picker-notice-action-desktop = Klik elemen untuk memilihnya di Inspektur +# Text displayed in `remote-node-picker-notice`, when the remote page is on Android +remote-node-picker-notice-action-touch = Ketuk elemen untuk memilihnya di Inspektur +# The text displayed in the button that is in the notice in the content page when the user +# clicks on the "Pick an element from the page" in about:devtools-toolbox inspector panel, +# when debugging a remote page. +remote-node-picker-notice-hide-button = Sembunyikan diff -Nru thunderbird-91.7.0+build2/l10n/id/dom/chrome/dom/dom.properties thunderbird-91.8.1+build1/l10n/id/dom/chrome/dom/dom.properties --- thunderbird-91.7.0+build2/l10n/id/dom/chrome/dom/dom.properties 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/dom/chrome/dom/dom.properties 2022-04-15 07:54:05.000000000 +0000 @@ -24,6 +24,7 @@ OnBeforeUnloadLeaveButton=Tinggalkan Laman EmptyGetElementByIdParam=String kosong ditempatkan ke getElementById(). SpeculationFailed=Pohon yang tak imbang telah ditulis lewat document.write() dan menyebabkan data dari jaringan untuk diuraikan ulang. Untuk bantuan kunjungi https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing +SpeculationFailed2=Pohon yang tak imbang telah ditulis lewat document.write() dan menyebabkan data dari jaringan untuk diuraikan ulang. Informasi lebih lanjut: https://developer.mozilla.org/en-US/docs/Glossary/speculative_parsing DocumentWriteIgnored=Pemanggilan fungsi document.write() dari skrip eksternal yang dimuat secara asinkron telah diabaikan. # LOCALIZATION NOTE (EditorFileDropFailed): Do not translate contenteditable, %S is the error message explaining why the drop failed. EditorFileDropFailed=Gagal meletakkan berkas ke dalam elemen contenteditable: %S. @@ -423,5 +424,12 @@ DocumentReleaseCaptureWarning=Document.releaseCapture() sudah usang. Gunakan Element.releasePointerCapture() saja. Untuk bantuan lebih lanjut, https://developer.mozilla.org/docs/Web/API/Element/releasePointerCapture # LOCALIZATION NOTE: Don't translate browser.runtime.lastError, %S is the error message from the unchecked value set on browser.runtime.lastError. +WebExtensionUncheckedLastError=nilai browser.runtime.lastError tidak diperiksa: %S # LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". +OffscreenCanvasToBlobWarning=OffscreenCanvas.toBlob() sudah usang. Gunakan OffscreenCanvas.convertToBlob() saja. + +# LOCALIZATION NOTE: Do not translate "IDBDatabase.createMutableFile()" +IDBDatabaseCreateMutableFileWarning=IDBDatabase.createMutableFile() sudah usang. Jika API ini dibakukan, kemungkinan besar akan dilakukan di bawah upaya Origin Private File System pada https://bugzil.la/1748667. +# LOCALIZATION NOTE: Do not translate "IDBMutableFile.open()" +IDBMutableFileOpenWarning=IDBDatabase.open() sudah usang. Jika API ini dibakukan, kemungkinan besar akan dilakukan di bawah upaya Origin Private File System pada https://bugzil.la/1748667. diff -Nru thunderbird-91.7.0+build2/l10n/id/security/manager/security/certificates/certManager.ftl thunderbird-91.8.1+build1/l10n/id/security/manager/security/certificates/certManager.ftl --- thunderbird-91.7.0+build2/l10n/id/security/manager/security/certificates/certManager.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/security/manager/security/certificates/certManager.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -4,131 +4,94 @@ certmgr-title = .title = Pengelola Sertifikat - certmgr-tab-mine = .label = Sertifikat Anda - certmgr-tab-remembered = .label = Keputusan Otentikasi - certmgr-tab-people = .label = Perseorangan - certmgr-tab-servers = .label = Server - certmgr-tab-ca = .label = Otoritas - certmgr-mine = Anda memiliki sertifikat dari organisasi berikut ini yang mengenali Anda certmgr-remembered = Sertifikat ini digunakan untuk mengidentifikasi Anda ke situs web. certmgr-people = Anda memiliki sertifikat di berkas yang mengenali orang ini certmgr-server = Entri ini mengidentifikasi pengecualian kesalahan sertifikat server certmgr-ca = Anda memiliki sertifikat pada berkas yang mengidentifikasi otoritas sertifikat ini - certmgr-edit-ca-cert = .title = Ubah pengaturan kepercayaan sertifikat CA .style = width: 48em; - certmgr-edit-cert-edit-trust = Ubah pengaturan kepercayaan: - certmgr-edit-cert-trust-ssl = .label = Sertifikat ini dapat mengidentifikasi situs web. - certmgr-edit-cert-trust-email = .label = Sertifikat ini dapat mengidentifikasi pengguna email. - certmgr-delete-cert = .title = Hapus Sertifikat .style = width: 48em; height: 24em; - certmgr-cert-host = .label = Host - certmgr-cert-name = .label = Nama Sertifikat - certmgr-cert-server = .label = Server - certmgr-override-lifetime = .label = Umur - certmgr-token-name = .label = Perangkat Keamanan - certmgr-begins-label = .label = Mulai Sejak - certmgr-expires-label = .label = Kedaluwarsa Pada - certmgr-email = .label = Alamat Surel - certmgr-serial = .label = Nomor Seri - certmgr-view = .label = Tampilkan… .accesskey = T - certmgr-edit = .label = Ubah Kepercayaan… .accesskey = K - certmgr-export = .label = Ekspor… .accesskey = k - certmgr-delete = .label = Hapus… .accesskey = H - certmgr-delete-builtin = .label = Hapus atau Tidak Lagi Percayai… .accesskey = L - certmgr-backup = .label = Buat Cadangan… .accesskey = C - certmgr-backup-all = .label = Buat Cadangan Keseluruhan… .accesskey = u - certmgr-restore = .label = Impor… .accesskey = I - certmgr-add-exception = .label = Tambah Pengecualian… .accesskey = P - exception-mgr = .title = Tambahkan Pengecualian Keamanan - exception-mgr-extra-button = .label = Konfirmasi Pengecualian Keamanan .accesskey = K - exception-mgr-supplemental-warning = Bank, toko, atau situs publik yang sah tidak akan menanyakan hal berikut kepada Anda. - exception-mgr-cert-location-url = .value = Lokasi: - exception-mgr-cert-location-download = .label = Unduh Sertifikat .accesskey = U - exception-mgr-cert-status-view-cert = .label = Tampilkan… .accesskey = T - exception-mgr-permanent = .label = Simpan pengecualian secara permanen .accesskey = m - pk11-bad-password = Sandi yang dimasukkan salah. pkcs12-decode-err = Gagal mendekode berkas. Format PKCS #12 salah, terkorupsi, atau sandi yang dimasukkan salah. pkcs12-unknown-err-restore = Gagal memulihkan berkas PKCS #12 karena alasan yang tidak diketahui. @@ -161,38 +124,30 @@ .title = Hapus Sertifikat Anda delete-user-cert-confirm = Yakin untuk menghapus sertifikat berikut? delete-user-cert-impact = Jika Anda menghapus salah satu sertifikat Anda, Anda tidak akan dapat menggunakannya lagi untuk memastikan identitas Anda. - - delete-ssl-override-title = .title = Hapus Pengecualian untuk Sertifikat Server delete-ssl-override-confirm = Yakin akan menghapus pengecualian server ini? delete-ssl-override-impact = Jika server dihapus dari pengecualian, Anda mengembalikan pemeriksaan yang biasanya dilakukan untuk server tersebut dan mengharuskan server tersebut untuk menggunakan sertifikat yang valid. - delete-ca-cert-title = .title = Hapus atau Tidak Lagi Mempercayai Sertifikat CA delete-ca-cert-confirm = Anda telah meminta untuk menghapus sertifikat CA ini. Untuk sertifikat bawaan, semua kepercayaan akan dihapus yang efeknya sama. Yakin ingin menghapus atau tidak lagi mempercayai sertifikat ini? delete-ca-cert-impact = Jika Anda menghapus atau tidak lagi mempercayai sertifikat milik otoritas sertifikat (CA), aplikasi ini tidak akan lagi mempercayai sertifikat yang diterbitkan CA tersebut. - - delete-email-cert-title = .title = Hapus Sertifikat Surel delete-email-cert-confirm = Yakin ingin menghapus sertifikat email perorangan ini? delete-email-cert-impact = Jika Anda menghapus sertifikat email seseorang, Anda tidak akan bisa lagi mengirim email terenkripsi kepada orang tersebut. - # Used for semi-uniquely representing a cert. # # Variables: # $serialNumber : the serial number of the cert in AA:BB:CC hex format. cert-with-serial = .value = Sertifikat dengan nomor seri: { $serialNumber } - -## Cert Viewer - # Used to indicate that the user chose not to send a client authentication certificate to a server that requested one in a TLS handshake. send-no-client-certificate = Tidak mengirim sertifikat klien - # Used when no cert is stored for an override no-cert-stored-for-override = (Tidak Disimpan) +# When a certificate is unavailable (for example, it has been deleted or the token it exists on has been removed). +certificate-not-available = (Tidak tersedia) ## Used to show whether an override is temporary or permanent diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/chrome/mozapps/extensions/extensions.properties thunderbird-91.8.1+build1/l10n/id/toolkit/chrome/mozapps/extensions/extensions.properties --- thunderbird-91.7.0+build2/l10n/id/toolkit/chrome/mozapps/extensions/extensions.properties 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/chrome/mozapps/extensions/extensions.properties 2022-04-15 07:54:04.000000000 +0000 @@ -68,6 +68,7 @@ type.plugin.name=Plugin type.dictionary.name=Kamus type.service.name=Layanan +type.sitepermission.name=Izin Situs type.legacy.name=Ekstensi Peninggalan type.unsupported.name=Tak didukung @@ -80,5 +81,7 @@ listHeading.locale=Kelola bahasa Anda listHeading.dictionary=Kelola kamus Anda +listHeading.sitepermission=Kelola Izin Situs Anda + searchLabel.extension=Temukan lebih banyak ekstensi searchLabel.theme=Temukan lebih banyak tema diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutAddons.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutAddons.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutAddons.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutAddons.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -3,109 +3,80 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. addons-page-title = Pengelola Pengaya - search-header = .placeholder = Cari addons.mozilla.org .searchbuttonlabel = Cari - search-header-shortcut = .key = f - list-empty-get-extensions-message = Dapatkan ekstensi dan tema di { $domain } - +list-empty-get-dictionaries-message = Dapatkan kamus di { $domain } +list-empty-get-language-packs-message = Dapatkan paket bahasa di { $domain } list-empty-installed = .value = Anda tidak memiliki pengaya terpasang jenis ini - list-empty-available-updates = .value = Tidak ada versi baru ditemukan - list-empty-recent-updates = .value = Anda masih belum memasang versi baru pengaya - list-empty-find-updates = .label = Periksa Versi Baru - list-empty-button = .label = Pelajari lebih lanjut tentang pengaya - help-button = Dukungan Pengaya sidebar-help-button-title = .title = Dukungan Pengaya - addons-settings-button = Pengaturan { -brand-short-name } sidebar-settings-button-title = .title = Pengaturan { -brand-short-name } - show-unsigned-extensions-button = .label = Beberapa ekstensi tidak dapat diverifikasi - show-all-extensions-button = .label = Tampilkan semua ekstensi - detail-version = .label = Versi - detail-last-updated = .label = Terakhir Diperbarui - detail-contributions-description = Pengembang pengaya ini memohon bantuan dukungan Anda untuk membantu kesinambungan pengembangan pengaya dengan memberikan kontribusi kecil. - detail-contributions-button = Berkontribusi .title = Berkontribusi dalam pengembangan pengaya ini .accesskey = k - detail-update-type = .value = Pemutakhiran Otomatis - detail-update-default = .label = Bawaan .tooltiptext = Otomatis pasang pemutakhiran hanya jika pengaturan bawaan diatur demikian - detail-update-automatic = .label = Aktif .tooltiptext = Otomatis memasang pemutakhiran - detail-update-manual = .label = Mati .tooltiptext = Jangan otomatis memasang pemutakhiran - # Used as a description for the option to allow or block an add-on in private windows. detail-private-browsing-label = Jalankan di Jendela Pribadi - # Some add-ons may elect to not run in private windows by setting incognito: not_allowed in the manifest. This # cannot be overridden by the user. detail-private-disallowed-label = Tidak Diizinkan di Jendela Pribadi detail-private-disallowed-description2 = Ekstensi ini tidak berjalan saat penjelajahan pribadi. Pelajari lebih lanjut - # Some special add-ons are privileged, run in private windows automatically, and this permission can't be revoked detail-private-required-label = Membutuhkan Akses ke Jendela Pribadi detail-private-required-description2 = Ekstensi ini memiliki akses ke aktivitas daring Anda saat penjelajahan pribadi. Pelajari lebih lanjut - detail-private-browsing-on = .label = Izinkan .tooltiptext = Aktifkan di Penjelajahan Pribadi - detail-private-browsing-off = .label = Jangan Izinkan .tooltiptext = Nonaktifkan di Penjelajahan Pribadi - detail-home = .label = Beranda - detail-home-value = .value = { detail-home.label } - detail-repository = .label = Profil Pengaya - detail-repository-value = .value = { detail-repository.label } - detail-check-for-updates = .label = Periksa versi baru .accesskey = v .tooltiptext = Periksa versi baru pengaya ini - detail-show-preferences = .label = { PLATFORM() -> @@ -122,38 +93,26 @@ [windows] Ubah pengaturan pengaya ini *[other] Ubah pengaturan pengaya ini } - detail-rating = .value = Peringkat - addon-restart-now = .label = Mulai ulang sekarang - disabled-unsigned-heading = .value = Beberapa pengaya telah dinonaktifkan - disabled-unsigned-description = Pengaya berikut belum diverifikasi untuk digunakan di { -brand-short-name }. Anda dapat atau minta pengembangnya untuk memverifikasi. - disabled-unsigned-learn-more = Pelajari tentang usaha kami untuk menjaga keselamatan daring Anda. - disabled-unsigned-devinfo = Pengembang yang tertarik untuk memverifikasi pengayanya dapat terus melanjutkan membaca kami. - plugin-deprecation-description = Kehilangan sesuatu? Beberapa plugin tidak didukung lagi oleh { -brand-short-name }. - legacy-warning-show-legacy = Tampilkan ekstensi peninggalan - legacy-extensions = .value = Ekstensi Peninggalan - legacy-extensions-description = Ekstensi ini tidak memenuhi standar { -brand-short-name } saat ini sehingga telah dinonaktifkan. - private-browsing-description2 = { -brand-short-name } mengubah cara kerja ekstensi di mode penjelajahan pribadi. Setiap ekstensi baru yang Anda tambahkan ke { -brand-short-name } tidak akan berjalan secara baku di Jendela Pribadi. Kecuali Anda mengizinkannya dalam pengaturan, ekstensi tidak akan berfungsi saat menjelajah secara pribadi dan tidak akan memiliki akses ke aktivitas daring Anda pada jendela pribadi tersebut. Kami telah membuat perubahan ini untuk menjaga penelusuran pribadi Anda tetap pribadi. - addon-category-discover = Rekomendasi addon-category-discover-title = .title = Rekomendasi @@ -178,6 +137,9 @@ addon-category-recent-updates = Versi Baru addon-category-recent-updates-title = .title = Versi Baru +addon-category-sitepermission = Izin Situs +addon-category-sitepermission-title = + .title = Izin Situs ## These are global warnings @@ -189,7 +151,6 @@ extensions-warning-update-security-button = Aktifkan .title = Aktifkan pemeriksaan keamanan pemutakhiran pengaya - ## Strings connected to add-on updates addon-updates-check-for-updates = Periksa Versi Baru @@ -235,42 +196,33 @@ # This is displayed in the page options menu addon-manage-extensions-shortcuts = Kelola Pintasan Ekstensi .accesskey = K - shortcuts-no-addons = Anda tidak memiliki ekstensi yang aktif. shortcuts-no-commands = Ekstensi berikut tidak memiliki pintasan: shortcuts-input = .placeholder = Ketikkan pintasan - shortcuts-browserAction2 = Aktifkan tombol bilah alat shortcuts-pageAction = Aktifkan tindakan laman shortcuts-sidebarAction = Aktifkan/Nonaktifkan bilah samping - shortcuts-modifier-mac = Sertakan Ctrl, Alt, atau ⌘ shortcuts-modifier-other = Sertakan Ctrl atau Alt shortcuts-invalid = Kombinasi tidak valid shortcuts-letter = Ketikkan huruf shortcuts-system = Tidak bisa menimpa pintasan { -brand-short-name } - # String displayed in warning label when there is a duplicate shortcut shortcuts-duplicate = Pintasan ganda - # String displayed when a keyboard shortcut is already assigned to more than one add-on # Variables: # $shortcut (string) - Shortcut string for the add-on shortcuts-duplicate-warning-message = { $shortcut } digunakan sebagai pintasan di lebih dari satu tempat. Pintasan duplikat dapat menyebabkan perilaku yang tidak terduga. - # String displayed when a keyboard shortcut is already used by another add-on # Variables: # $addon (string) - Name of the add-on shortcuts-exists = Sudah digunakan oleh { $addon } - shortcuts-card-expand-button = { $numberToShow -> *[other] Tampilkan { $numberToShow } Lainnya } - shortcuts-card-collapse-button = Lebih Sedikit - header-back-button = .title = Mundur @@ -281,15 +233,12 @@ discopane-intro = Ekstensi dan tema seperti layaknya aplikasi untuk browser Anda, dan mereka bisa digunakan untuk melindungi kata sandi, mengunduh video, menemukan penawaran, memblokir iklan yang mengganggu, mengubah tampilan peramban Anda, dan banyak lagi. Program perangkat lunak kecil ini banyak dikembangkan oleh pihak ketiga. Berikut adalah pilihan yang disarankan { -brand-product-name } berdasarkan keamanan, kinerja, dan fungsionalitas mereka. - # Notice to make user aware that the recommendations are personalized. discopane-notice-recommendations = Beberapa rekomendasi ini dipersonalisasi. Rekomendasi tersebut didasarkan pada ekstensi lain yang Anda pasang, preferensi profil, dan statistik penggunaan. discopane-notice-learn-more = Pelajari lebih lanjut - privacy-policy = Kebijakan Privasi - # Refers to the author of an add-on, shown below the name of the add-on. # Variables: # $author (string) - The name of the add-on developer. @@ -304,7 +253,7 @@ # the detailed add-on view is opened, from where the add-on can be managed. manage-addon-button = Kelola find-more-addons = Temukan lebih banyak pengaya - +find-more-themes = Temukan lebih banyak tema # This is a label for the button to open the "more options" menu, it is only # used for screen readers. addon-options-button = @@ -330,46 +279,39 @@ details-addon-button = Detail release-notes-addon-button = Catatan Rilis permissions-addon-button = Hak Akses - extension-enabled-heading = Aktif extension-disabled-heading = Nonaktif - theme-enabled-heading = Aktif theme-disabled-heading = Nonaktif - +theme-monochromatic-heading = Warna +theme-monochromatic-subheading = Warna baru yang semarak dari { -brand-product-name }. Tersedia untuk waktu terbatas. plugin-enabled-heading = Aktif plugin-disabled-heading = Nonaktif - dictionary-enabled-heading = Aktif dictionary-disabled-heading = Nonaktif - locale-enabled-heading = Aktif locale-disabled-heading = Nonaktif - +sitepermission-enabled-heading = Diaktifkan +sitepermission-disabled-heading = Dinonaktifkan always-activate-button = Selalu Aktif never-activate-button = Jangan Pernah Aktifkan - addon-detail-author-label = Penyusun addon-detail-version-label = Versi addon-detail-last-updated-label = Terakhir Diperbarui addon-detail-homepage-label = Beranda addon-detail-rating-label = Peringkat - # Message for add-ons with a staged pending update. install-postponed-message = Ekstensi ini akan diperbarui ketika { -brand-short-name } dimulai ulang. install-postponed-button = Perbarui Sekarang - # The average rating that the add-on has received. # Variables: # $rating (number) - A number between 0 and 5. The translation should show at most one digit after the comma. five-star-rating = .title = Peringkat { NUMBER($rating, maximumFractionDigits: 1) } dari 5 - # This string is used to show that an add-on is disabled. # Variables: # $name (string) - The name of the add-on addon-name-disabled = { $name } (dinonaktifkan) - # The number of reviews that an add-on has received on AMO. # Variables: # $numberOfReviews (number) - The number of reviews received @@ -384,14 +326,12 @@ # $addon (string) - Name of the add-on pending-uninstall-description = { $addon } telah dihapus. pending-uninstall-undo-button = Batal - addon-detail-updates-label = Izinkan pembaruan otomatis addon-detail-updates-radio-default = Baku addon-detail-updates-radio-on = Aktif addon-detail-updates-radio-off = Nonaktif addon-detail-update-check-label = Periksa Versi Baru install-update-button = Perbarui - # This is the tooltip text for the private browsing badge in about:addons. The # badge is the private browsing icon included next to the extension's name. addon-badge-private-browsing-allowed2 = @@ -407,7 +347,6 @@ addon-badge-recommended2 = .title = { -brand-product-name } hanya menyarankan ekstensi yang memenuhi standar keamanan dan kinerja kami. .aria-label = { addon-badge-recommended2.title } - # We hard code "Mozilla" in the string below because the extensions are built # by Mozilla and we don't want forks to display "by Fork". addon-badge-line3 = @@ -421,19 +360,15 @@ available-updates-heading = Versi Baru yang Tersedia recent-updates-heading = Versi Terkini - release-notes-loading = Memuat… release-notes-error = Maaf, galat terjadi ketika memuat catatan rilis. - addon-permissions-empty = Ekstensi ini tidak memerlukan izin apa pun - addon-permissions-required = Izin yang diperlukan untuk fungsi inti: addon-permissions-optional = Izin opsional untuk fungsi tambahan: addon-permissions-learnmore = Pelajari lebih lanjut tentang perizinan - recommended-extensions-heading = Ekstensi yang Disarankan recommended-themes-heading = Tema yang Disarankan - +addon-sitepermissions-required = Berikan kemampuan berikut untuk { $hostname }: # A recommendation for the Firefox Color theme shown at the bottom of the theme # list view. The "Firefox Color" name itself should not be translated. recommended-theme-1 = Merasa kreatif? Buat tema Anda sendiri dengan Firefox Color. @@ -446,12 +381,11 @@ dictionary-heading = Kelola kamus Anda locale-heading = Kelola bahasa Anda updates-heading = Kelola Pembaruan Anda +sitepermission-heading = Kelola Izin Situs Anda discover-heading = Personalisasikan { -brand-short-name } Anda shortcuts-heading = Kelola Pintasan Ekstensi - default-heading-search-label = Temukan lebih banyak pengaya addons-heading-search-input = .placeholder = Cari addons.mozilla.org - addon-page-options-button = .title = Alat untuk semua pengaya diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutCompat.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutCompat.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutCompat.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutCompat.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -11,3 +11,12 @@ text-no-interventions = Tidak ada intervensi yang digunakan text-no-overrides = Tidak ada penggantian UA yang digunakan text-title = about:compat + +## Do not translate "SmartBlock". For reference, SmartBlock is a feature +## of Firefox anti-tracking which fixes website breakage caused when +## trackers are blocked, by acting just enough like those trackers to fix the +## breakage. SmartBlock also contains special fixes for sites broken by +## Firefox's Total Cookie Protection feature. + +label-smartblock = Perbaikan SmartBlock +text-no-smartblock = Tidak ada perbaikan SmartBlock yang digunakan diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutHttpsOnlyError.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutHttpsOnlyError.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutHttpsOnlyError.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutHttpsOnlyError.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -4,7 +4,7 @@ about-httpsonly-title-alert = Peringatan Mode Hanya HTTPS about-httpsonly-title-connection-not-available = Sambungan Aman Tidak Tersedia - +about-httpsonly-title-site-not-available = Situs Aman Tidak Tersedia # Variables: # $websiteUrl (String) - Url of the website that failed to load. Example: www.example.com about-httpsonly-explanation-unavailable2 = Anda telah mengaktifkan Mode Hanya HTTPS untuk keamanan yang ditingkatkan tetapi versi HTTPS { $websiteUrl } tidak tersedia. @@ -12,7 +12,6 @@ about-httpsonly-explanation-nosupport = Kemungkinan besar, situs web tidak mendukung HTTPS. about-httpsonly-explanation-risk = Mungkin juga ada penyerang yang terlibat. Jika Anda memutuskan untuk mengunjungi situs web, Anda tidak boleh memasukkan informasi sensitif seperti sandi, surel, atau detail kartu kredit. about-httpsonly-explanation-continue = Jika dilanjutkan, Mode Hanya HTTPS akan dinonaktifkan sementara untuk situs ini. - about-httpsonly-button-continue-to-site = Lanjutkan ke Situs HTTP about-httpsonly-button-go-back = Kembali about-httpsonly-link-learn-more = Pelajari Lebih Lanjut… diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutNetworking.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutNetworking.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutNetworking.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutNetworking.ftl 2022-04-15 07:54:05.000000000 +0000 @@ -27,6 +27,7 @@ about-networking-addresses = Alamat about-networking-expires = Hangus (Detik) about-networking-originAttributesSuffix = Kunci Isolasi +about-networking-flags = Flag ekstra about-networking-messages-sent = Pesan Terkirim about-networking-messages-received = Pesan Diterima about-networking-bytes-sent = Byte Dikirim diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutProcesses.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutProcesses.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutProcesses.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutProcesses.ftl 2022-04-15 07:54:05.000000000 +0000 @@ -4,7 +4,6 @@ # Page title about-processes-title = Manajer Proses - # The Actions column about-processes-column-action = .title = Tindakan @@ -25,12 +24,6 @@ ## Process names ## Variables: ## $pid (String) The process id of this process, assigned by the OS. -## $origin (String) The domain name for this process. -## $type (String) The raw type for this process. Used for unknown processes. - -## Process names -## Variables: -## $pid (String) The process id of this process, assigned by the OS. about-processes-browser-process = { -brand-short-name } ({ $pid }) about-processes-web-process = Shared Web Process ({ $pid }) @@ -47,7 +40,6 @@ about-processes-remote-sandbox-broker-process = Broker Kotak Pasir Daring ({ $pid }) about-processes-fork-server-process = Server Fork ({ $pid }) about-processes-preallocated-process = Praalokasi ({ $pid }) - # Unknown process names # Variables: # $pid (String) The process id of this process, assigned by the OS. @@ -60,6 +52,7 @@ ## $origin (String) The domain name for this process. about-processes-web-isolated-process = { $origin } ({ $pid }) +about-processes-web-serviceworker = { $origin } ({ $pid }, serviceworker) about-processes-web-large-allocation-process = { $origin } ({ $pid }, besar) about-processes-with-coop-coep-process = { $origin } ({ $pid }, terisolasi cross-origin) about-processes-web-isolated-process-private = { $origin } — Pribadi ({ $pid }) @@ -82,7 +75,6 @@ { $active -> *[other] { $active } utas aktif dari { $number }: { $list } } - # Single-line summary of threads (idle process) # Variables: # $number (Number) The number of threads in the process. Typically larger @@ -93,25 +85,21 @@ { $number -> *[other] { $number } utas tidak aktif } - # Thread details # Variables: # $name (String) The name assigned to the thread. # $tid (String) The thread id of this thread, assigned by the OS. about-processes-thread-name-and-id = { $name } .title = ID utas: { $tid } - # Tab # Variables: # $name (String) The name of the tab (typically the title of the page, might be the url while the page is loading). about-processes-tab-name = Tab: { $name } about-processes-preloaded-tab = Tab Baru Pramuat - # Single subframe # Variables: # $url (String) The full url of this subframe. about-processes-frame-name-one = Subframe: { $url } - # Group of subframes # Variables: # $number (Number) The number of subframes in this group. Always ≥ 1. @@ -130,10 +118,8 @@ # Common case. about-processes-cpu = { NUMBER($percent, maximumSignificantDigits: 2, style: "percent") } .title = Waktu CPU total: { NUMBER($total, maximumFractionDigits: 0) }{ $unit } - # Special case: data is not available yet. about-processes-cpu-user-and-kernel-not-ready = (mengukur) - # Special case: process or thread is currently idle. about-processes-cpu-idle = menganggur .title = Waktu CPU total: { NUMBER($total, maximumFractionDigits: 2) }{ $unit } @@ -152,7 +138,6 @@ # Common case. about-processes-total-memory-size-changed = { NUMBER($total, maximumFractionDigits: 0) }{ $totalUnit } .title = Evolusi: { $deltaSign }{ NUMBER($delta, maximumFractionDigits: 0) }{ $deltaUnit } - # Special case: no change. about-processes-total-memory-size-no-change = { NUMBER($total, maximumFractionDigits: 0) }{ $totalUnit } diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutSupport.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutSupport.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutSupport.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutSupport.ftl 2022-04-15 07:54:05.000000000 +0000 @@ -4,7 +4,6 @@ page-title = Informasi Pemecahan Masalah page-subtitle = Laman ini berisi informasi teknis yang mungkin berguna ketika Anda berusaha mengatasi masalah. Jika Anda mencari jawaban untuk pertanyaan umum tentang { -brand-short-name }, silakan kunjungi situs web layanan dukungan kami. - crashes-title = Laporan Kerusakan crashes-id = ID Laporan crashes-send-date = Dikirim @@ -55,12 +54,14 @@ app-basics-build-config = Konfigurasi Build app-basics-user-agent = User Agent app-basics-os = OS +app-basics-os-theme = Tema Sistem Operasi # Rosetta is Apple's translation process to run apps containing x86_64 # instructions on Apple Silicon. This should remain in English. app-basics-rosetta = Rosetta Translated app-basics-memory-use = Penggunaan Memori app-basics-performance = Kinerja app-basics-service-workers = Service Worker Terdaftar +app-basics-third-party = Modul Pihak Ketiga app-basics-profiles = Profil app-basics-launcher-process-status = Proses Peluncur app-basics-multi-process-support = Jendela Multiproses @@ -124,7 +125,6 @@ sandbox-sys-call-proc-type = Jenis Proses sandbox-sys-call-number = Syscall sandbox-sys-call-args = Argumen - troubleshoot-mode-title = Diagnosis masalah restart-in-troubleshoot-mode-label = Mode Pemecahan Masalah… clear-startup-cache-title = Coba bersihkan tembolok permulaan @@ -185,23 +185,18 @@ # Variables # $days (Integer) - Number of days of crashes to log report-crash-for-days = Laporan Kerusakan dalam { $days } Hari Terakhir - # Variables # $minutes (integer) - Number of minutes since crash crashes-time-minutes = { $minutes } menit yang lalu - # Variables # $hours (integer) - Number of hours since crash crashes-time-hours = { $hours } jam yang lalu - # Variables # $days (integer) - Number of days since crash crashes-time-days = { $days } hari yang lalu - # Variables # $reports (integer) - Number of pending reports pending-reports = Semua Laporan Kerusakan (termasuk { $reports } kerusakan yang tertunda pada rentang waktu yang ditentukan) - raw-data-copied = Data mentah telah disalin ke papan klip text-copied = Teks telah disalin ke clipboard @@ -214,11 +209,9 @@ # Variables # $driverVersion - The graphics driver version string try-newer-driver = Diblokir untuk versi penggerak grafik Anda. Coba perbarui penggerak grafik Anda ke versi { $driverVersion } atau yang lebih baru. - # "ClearType" is a proper noun and should not be translated. Feel free to leave English strings if # there are no good translations, these are only used in about:support clear-type-parameters = Parameter ClearType - compositing = Compositing hardware-h264 = Dekode H264 Perangkat Keras main-thread-no-omtc = thread utama, tanpa OMTC @@ -233,7 +226,6 @@ found = Ditemukan missing = Hilang - gpu-process-pid = GPUProcessPid gpu-process = GPUProcess gpu-description = Deskripsi @@ -256,19 +248,15 @@ webgl2-version = Versi Penggerak WebGL 2 webgl2-driver-extensions = Ekstensi Penggerak WebGL 2 webgl2-extensions = Ekstensi WebGL 2 - # Variables # $bugNumber (string) - Bug number on Bugzilla support-blocklisted-bug = Dicekal karena masalah yang diketahui: bug { $bugNumber } - # Variables # $failureCode (string) - String that can be searched in the source tree. unknown-failure = Dicekal: kode kegagalan { $failureCode } - d3d11layers-crash-guard = Compositor D3D11 glcontext-crash-guard = OpenGL wmfvpxvideo-crash-guard = WMF VPX Video Decoder - reset-on-next-restart = Setel Ulang pada Mulai Ulang Berikutnya gpu-process-kill-button = Matikan Proses GPU gpu-device-reset = Reset Perangkat @@ -278,10 +266,8 @@ off-main-thread-paint-enabled = Off Main Thread Painting Diaktifkan off-main-thread-paint-worker-count = Jumlah Off Main Thread Painting Worker target-frame-rate = Tingkat Target Bingkai - min-lib-versions = Versi minimum diharapkan loaded-lib-versions = Versi yang digunakan - has-seccomp-bpf = Seccomp-BPF (Pemfilteran Pemanggilan Sistem - System Call Filtering) has-seccomp-tsync = Sinkronisasi Utas Seccomp has-user-namespaces = Ruang Nama Pengguna @@ -295,23 +281,19 @@ sandbox-proc-type-file = konten berkas sandbox-proc-type-media-plugin = plugin media sandbox-proc-type-data-decoder = dekoder data - startup-cache-title = Tembolok Permulaan startup-cache-disk-cache-path = Jalur Tembolok Disk startup-cache-ignore-disk-cache = Abaikan Tembolok Disk startup-cache-found-disk-cache-on-init = Tembolok Disk di Init ditemukan startup-cache-wrote-to-disk-cache = Menulis ke Tembolok Disk - launcher-process-status-0 = Diaktifkan launcher-process-status-1 = Dinonaktifkan karena kegagalan launcher-process-status-2 = Dinonaktifkan secara paksa launcher-process-status-unknown = Status tak diketahui - # Variables # $remoteWindows (integer) - Number of remote windows # $totalWindows (integer) - Number of total windows multi-process-windows = { $remoteWindows }/{ $totalWindows } - # Variables # $fissionWindows (integer) - Number of remote windows # $totalWindows (integer) - Number of total windows @@ -320,13 +302,13 @@ fission-status-experiment-treatment = Diaktifkan oleh eksperimen fission-status-disabled-by-e10s-env = Dinonaktifkan oleh lingkungan fission-status-enabled-by-env = Diaktifkan oleh lingkungan +fission-status-disabled-by-env = Dinonaktifkan oleh lingkungan fission-status-disabled-by-safe-mode = Dinonaktifkan oleh mode aman fission-status-enabled-by-default = Diaktifkan secara baku fission-status-disabled-by-default = Dinonaktifkan secara baku fission-status-enabled-by-user-pref = Diaktifkan oleh pengguna fission-status-disabled-by-user-pref = Dinonaktifkan oleh pengguna fission-status-disabled-by-e10s-other = E10s dinonaktifkan - async-pan-zoom = Geser/Perbesaran Asinkron apz-none = tidak ada wheel-enabled = input wheel diaktifkan @@ -363,7 +345,6 @@ support-remote-experiments-name = Nama support-remote-experiments-branch = Cabang Eksperimen support-remote-experiments-see-about-studies = Lihat about:studies untuk informasi lebih lanjut, termasuk cara menonaktifkan masing-masing percobaan atau menonaktifkan { -brand-short-name } untuk menjalankan jenis eksperimen ini di masa mendatang. - support-remote-features-title = Fitur Jarak Jauh support-remote-features-name = Nama support-remote-features-status = Status diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutThirdParty.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutThirdParty.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutThirdParty.ftl 2022-03-07 21:39:02.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutThirdParty.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -26,6 +26,8 @@ .title = Modul ini tidak memblokir aplikasi karena dimuat di latar belakang. third-party-unsigned-icon = .title = Modul ini tidak ditandatangani +third-party-warning-icon = + .title = { -brand-short-name } mogok karena kode program dari modul ini third-party-status-loaded = Dimuat third-party-status-blocked = Terblokir third-party-status-redirected = Dialihkan diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutWebrtc.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutWebrtc.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/aboutWebrtc.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/aboutWebrtc.ftl 2022-04-15 07:54:05.000000000 +0000 @@ -8,7 +8,6 @@ # The text "WebRTC" is a proper noun and should not be translated. about-webrtc-document-title = Internal WebRTC - # "about:webrtc" is a internal browser URL and should not be # translated. This string is used as a title for a file save dialog box. about-webrtc-save-page-dialog-title = simpan about:webrtc dengan nama @@ -19,6 +18,8 @@ about-webrtc-aec-logging-off-state-label = Mulai Pencatatan AEC about-webrtc-aec-logging-on-state-label = Hentikan Pencatatan AEC about-webrtc-aec-logging-on-state-msg = Pencatatan AEC aktif (bicara dengan pemanggil selama beberapa menit lalu hentikan penangkapan) +# The autorefresh checkbox causes the page to autorefresh its content when checked +about-webrtc-auto-refresh-label = Segarkan Otomatis ## @@ -73,16 +74,13 @@ ## - # This adjective is used to label a table column. Cells in this column contain # the localized javascript string representation of "true" or are left blank. about-webrtc-nominated = Dinominasikan - # This adjective is used to label a table column. Cells in this column contain # the localized javascript string representation of "true" or are left blank. # This represents an attribute of an ICE candidate. about-webrtc-selected = Dipilih - about-webrtc-save-page-label = Simpan Laman about-webrtc-debug-mode-msg-label = Mode Debug about-webrtc-debug-mode-off-state-label = Mulai Mode Debug @@ -108,7 +106,6 @@ ## - about-webrtc-local-candidate = Kandidat Lokal about-webrtc-remote-candidate = Kandidat Jarak Jauh about-webrtc-raw-candidates-heading = Semua Kandidat Mentah @@ -128,6 +125,7 @@ about-webrtc-decoder-label = Dekoder about-webrtc-encoder-label = Enkoder about-webrtc-show-tab-label = Tampilkan tab +about-webrtc-current-framerate-label = Kecepatan bingkai about-webrtc-width-px = Lebar (px) about-webrtc-height-px = Tinggi (px) about-webrtc-consecutive-frames = Bingkai Berturutan @@ -149,36 +147,26 @@ # An option whose value will not be displayed but instead noted as having been # provided about-webrtc-configuration-element-provided = Disediakan - # An option whose value will not be displayed but instead noted as having not # been provided about-webrtc-configuration-element-not-provided = Tidak Disediakan - # The options set by the user in about:config that could impact a WebRTC call about-webrtc-custom-webrtc-configuration-heading = Preferensi WebRTC Diatur Pengguna - # Section header for estimated bandwidths of WebRTC media flows about-webrtc-bandwidth-stats-heading = Perkiraan Bandwidth - # The ID of the MediaStreamTrack about-webrtc-track-identifier = Pengenal Jalur - # The estimated bandwidth available for sending WebRTC media in bytes per second about-webrtc-send-bandwidth-bytes-sec = Bandwidth Pengiriman (byte/detik) - # The estimated bandwidth available for receiving WebRTC media in bytes per second about-webrtc-receive-bandwidth-bytes-sec = Bandwidth Penerimaan (byte/detik) - # Maximum number of bytes per second that will be padding zeros at the ends of packets about-webrtc-max-padding-bytes-sec = Padding Maksimum (byte/detik) - # The amount of time inserted between packets to keep them spaced out about-webrtc-pacer-delay-ms = Penundaan Pacer md - # The amount of time it takes for a packet to travel from the local machine to the remote machine, # and then have a packet return about-webrtc-round-trip-time-ms = RTT md - # This is a section heading for video frame statistics for a MediaStreamTrack. # see https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack. # Variables: @@ -204,7 +192,6 @@ { $packets -> *[other] { $packets } paket diterima } - # This is the total number of packets lost by the PeerConnection. # Variables: # $packets (Number) - The number of packets lost. @@ -212,7 +199,6 @@ { $packets -> *[other] { $packets } paket hilang } - # This is the total number of packets sent by the PeerConnection. # Variables: # $packets (Number) - The number of packets sent. @@ -220,13 +206,11 @@ { $packets -> *[other] { $packets } paket dikirim } - # Jitter is the variance in the arrival time of packets. # See: https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats-jitter # Variables: # $jitter (Number) - The jitter. about-webrtc-jitter-label = Jitter { $jitter } - # ICE candidates arriving after the remote answer arrives are considered trickled # (an attribute of an ICE candidate). These are highlighted in the ICE stats # table with light blue background. @@ -239,12 +223,10 @@ # Variables: # $timestamp (Number) - The Unix Epoch time at which the SDP was set. about-webrtc-sdp-set-at-timestamp-local = Setel SDP Lokal pada stempel waktu { NUMBER($timestamp, useGrouping: "false") } - # This is used as a header for remote SDP. # Variables: # $timestamp (Number) - The Unix Epoch time at which the SDP was set. about-webrtc-sdp-set-at-timestamp-remote = Setel SDP Jarak Jauh pada stempel waktu { NUMBER($timestamp, useGrouping: "false") } - # This is used as a header for an SDP section contained in two columns allowing for side-by-side comparisons. # Variables: # $timestamp (Number) - The Unix Epoch time at which the SDP was set. @@ -253,7 +235,3 @@ ## -## - -## - diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/abuseReports.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/abuseReports.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/about/abuseReports.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/about/abuseReports.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -2,26 +2,22 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Localized string used as the dialog window title (a new behavior locked -# behind the "extensions.abuseReport.openDialog" preference). +# Localized string used as the dialog window title. # "Report" is a noun in this case, "Report for AddonName". # # Variables: # $addon-name (string) - Name of the add-on being reported abuse-report-dialog-title = Laporan untuk { $addon-name } - abuse-report-title-extension = Laporkan Ekstensi Ini ke { -vendor-short-name } +abuse-report-title-sitepermission = Laporkan pengaya Izin Situs Ini ke { -vendor-short-name } abuse-report-title-theme = Laporkan Tema Ini ke { -vendor-short-name } abuse-report-subtitle = Apa masalahnya? - # Variables: # $author-name (string) - Name of the add-on author abuse-report-addon-authored-by = oleh { $author-name } - abuse-report-learnmore = Tidak yakin masalah apa yang harus dipilih? Pelajari lebih lanjut tentang melaporkan ekstensi dan tema - abuse-report-submit-description = Jelaskan masalahnya (opsional) abuse-report-textarea = .placeholder = Akan lebih memudahkan bagi kami untuk menangani masalah jika memahami rinciannya. Harap jelaskan apa yang Anda alami. Terima kasih telah membantu kami menjaga Internet tetap sehat. @@ -37,12 +33,6 @@ abuse-report-submit-button = Kirim ## Message bars descriptions. - - -## Variables: -## $addon-name (string) - Name of the add-on - -## Message bars descriptions. ## ## Variables: ## $addon-name (string) - Name of the add-on @@ -52,6 +42,7 @@ abuse-report-messagebar-submitted = Terima kasih telah mengirimkan laporan. Apakah Anda ingin menghapus { $addon-name }? abuse-report-messagebar-submitted-noremove = Terima kasih telah mengirimkan laporan. abuse-report-messagebar-removed-extension = Terima kasih telah mengirimkan laporan. Anda telah menghapus ekstensi { $addon-name }. +abuse-report-messagebar-removed-sitepermission = Terima kasih telah mengirimkan laporan. Anda telah menghapus pengaya Izin Situs { $addon-name }. abuse-report-messagebar-removed-theme = Terima kasih telah mengirimkan laporan. Anda telah menghapus tema { $addon-name }. abuse-report-messagebar-error = Terjadi kesalahan saat mengirim laporan untuk { $addon-name }. abuse-report-messagebar-error-recent-submit = Laporan untuk { $addon-name } tidak terkirim karena laporan lain telah dikirimkan baru-baru ini. @@ -60,6 +51,8 @@ abuse-report-messagebar-action-remove-extension = Ya, Hapus abuse-report-messagebar-action-keep-extension = Tidak, Saya akan Menyimpannya +abuse-report-messagebar-action-remove-sitepermission = Ya, Hapus +abuse-report-messagebar-action-keep-sitepermission = Tidak, Saya Akan Mempertahankannya abuse-report-messagebar-action-remove-theme = Ya, Hapus abuse-report-messagebar-action-keep-theme = Tidak, Saya akan Menyimpannya abuse-report-messagebar-action-retry = Ulangi @@ -69,35 +62,32 @@ abuse-report-damage-reason-v2 = Ini merusak komputer saya atau membahayakan data saya abuse-report-damage-example = Misal: memuat malware atau mencuri data - abuse-report-spam-reason-v2 = Ini mengandung spam atau menyisipkan iklan yang tidak diinginkan abuse-report-spam-example = Misal: Memuat iklan di laman web - abuse-report-settings-reason-v2 = Ini mengubah setelan pencarian, beranda, atau tab baru tanpa memberitahu atau bertanya pada saya abuse-report-settings-suggestions = Sebelum melaporkan ekstensi, Anda dapat mencoba mengubah pengaturan Anda: abuse-report-settings-suggestions-search = Ubah setelan pencarian baku Anda abuse-report-settings-suggestions-homepage = Ubah beranda dan tab baru Anda - abuse-report-deceptive-reason-v2 = Berpura-pura menjadi sesuatu abuse-report-deceptive-example = Contoh: Deskripsi atau gambar yang menyesatkan - abuse-report-broken-reason-extension-v2 = Ini tidak berfungsi, tampilan situs web rusak, atau memperlambat { -brand-product-name } +abuse-report-broken-reason-sitepermission-v2 = Ini tidak berfungsi, tampilan situs web rusak, atau memperlambat { -brand-product-name } abuse-report-broken-reason-theme-v2 = Ini tidak berfungsi atau merusak tampilan peramban abuse-report-broken-example = Contoh: Fitur lambat, sulit digunakan, atau tidak berfungsi; bagian dari situs web tidak bisa dimuat atau terlihat aneh abuse-report-broken-suggestions-extension = Sepertinya Anda telah menemukan bug. Selain mengirimkan laporan di sini, cara terbaik untuk menyelesaikan masalah fungsionalitas adalah menghubungi pengembang ekstensi. Kunjungi situs web ekstensi untuk mendapatkan informasi pengembang. +abuse-report-broken-suggestions-sitepermission = + Sepertinya Anda telah menemukan bug. Selain mengirimkan laporan di sini, cara terbaik + untuk menyelesaikan masalah fungsionalitas adalah menghubungi pengembang situs web. + Kunjungi situs web untuk mendapatkan informasi pengembang. abuse-report-broken-suggestions-theme = Sepertinya Anda telah menemukan bug. Selain mengirimkan laporan di sini, cara terbaik untuk menyelesaikan masalah fungsionalitas adalah menghubungi pengembang tema. Kunjungi situs web tema untuk mendapatkan informasi pengembang. - abuse-report-policy-reason-v2 = Ini mengandung konten yang berisi kebencian, kekerasan, atau melanggar hukum abuse-report-policy-suggestions = Catatan: Masalah berkaitan dengan hak cipta dan merek dagang wajib dilaporkan dalama proses terpisah. Gunakan langkah ini untuk melaporkannya. - abuse-report-unwanted-reason-v2 = Saya tidak pernah menginginkannya dan tidak tahu bagaimana cara menghilangkannya abuse-report-unwanted-example = Contoh: Sebuah aplikasi memasang sesuatu tanpa izin saya - abuse-report-other-reason = Lainnya - diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/featuregates/features.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/featuregates/features.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/featuregates/features.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/featuregates/features.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -7,102 +7,89 @@ experimental-features-css-masonry2 = .label = CSS: Masonry Layout experimental-features-css-masonry-description = Mengaktifkan dukungan untuk fitur Layout CSS Masonry eksperimental. Lihat penjelasan untuk mendapatkan deskripsi fitur yang lebih lengkap. Untuk memberikan umpan balik, silakan berkomentar di isu GitHub ini atau bug ini. - # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. experimental-features-web-gpu2 = .label = API Web: WebGPU experimental-features-web-gpu-description2 = API baru ini menyediakan dukungan tingkat-rendah untuk melakukan komputasi dan perenderan grafis dengan menggunakan Unit Pemrosesan Grafik (GPU) dari perangkat atau komputer pengguna. Spesifikasi masih dalam proses pengembangan. Lihat bug 1602129 untuk detail lebih lanjut. - # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. experimental-features-media-avif = .label = Media: AVIF experimental-features-media-avif-description = Jika fitur ini diaktifkan, { -brand-short-name } akan mendukung format Berkas Gambar AV1 (AVIF). Ini adalah format berkas gambar diam yang memanfaatkan kemampuan algoritme kompresi video AV1 untuk mengurangi ukuran gambar. Lihat bug 1443863 untuk detail lebih lanjut. - # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. experimental-features-media-jxl = .label = Media: JPEG XL - +experimental-features-media-jxl-description = Dengan fitur ini diaktifkan, { -brand-short-name } mendukung format JPEG XL (JXL). Ini adalah format file gambar yang disempurnakan yang mendukung transisi lossless dari file JPEG tradisional. Lihat bug 1539075 untuk detail selengkapnya. # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. experimental-features-web-api-inputmode = .label = API Web: inputmode # "inputmode" and "contenteditable" are technical terms and shouldn't be translated. experimental-features-web-api-inputmode-description = Implementasi kami untuk atribut global inputmode telah diperbarui sesuai spesifikasi WHATWG. Namun kami masih perlu membuat perubahan lain juga, seperti memperbarui hal yang sama untuk konten contenteditable. Lihat bug 1205133 untuk detail lebih lanjut. - # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. experimental-features-css-constructable-stylesheets = .label = CSS: Constructable Stylesheet experimental-features-css-constructable-stylesheets-description = Penambahan konstruktor untuk antarmuka CSSylesheet serta berbagai perubahan yang terkait memungkinkan pembuatan stylesheet baru secara langsung tanpa harus menambahkan stylesheet ke HTML. Ini mempermudah penggunaan ulang stylesheet untuk digunakan dengan Shadow DOM. Lihat bug 1520690 untuk detal lebih lanjut. - experimental-features-devtools-color-scheme-simulation = .label = Alat Pengembang: Simulasi Skema Warna experimental-features-devtools-color-scheme-simulation-description = Menambahkan opsi untuk simulasi berbagai skema warna yang memungkinkan Anda untuk menguji media query @prefers-color-scheme. Menggunakan query ini memungkinkan stylesheet Anda merespons apakah pengguna lebih suka antarmuka yang terang atau gelap. Fitur ini memungkinkan Anda menguji kode tanpa harus mengubah setelan di peramban (atau sistem operasi, jika peramban mengikuti setelan skema warna keseluruhan sistem). Lihat bug 1550804 dan bug 1137699 untuk detail lebih lanjut. - experimental-features-devtools-execution-context-selector = .label = Alat Pengembang: Pemilih Konteks Eksekusi experimental-features-devtools-execution-context-selector-description = Fitur ini menampilkan tombol pada baris perintah konsol yang memungkinkan Anda mengubah konteks pada ekspresi yang dimasukkan untuk dieksekusi. Lihat bug 1605154 dan bug 1605153 untuk detail lebih lanjut. - experimental-features-devtools-compatibility-panel = .label = Alat Pengembang: Panel Kompabilitas experimental-features-devtools-compatibility-panel-description = Panel samping untuk Inspektur Laman yang menampilkan informasi yang merinci status kompatibilitas lintas peramban aplikasi Anda. Lihat bug 158464 untuk detail lebih lanjut. - # Do not translate 'SameSite', 'Lax' and 'None'. experimental-features-cookie-samesite-lax-by-default2 = .label = Kuki: SameSite=Lax secara baku experimental-features-cookie-samesite-lax-by-default2-description = Perlakukan kuki sebagai “SameSite=Lax” secara baku jika tidak ada atribut “SameSite” ditentukan. Pengembang harus memilih status quo saat ini dari penggunaan yang tidak terbatas dengan secara eksplisit menyatakan “SameSite=None””. - # Do not translate 'SameSite', 'Lax' and 'None'. experimental-features-cookie-samesite-none-requires-secure2 = .label = Kuki: SameSite=None memerlukan atribut aman experimental-features-cookie-samesite-none-requires-secure2-description = Kuki dengan atribut “SameSite=None” memerlukan atribut aman. Fitur ini memerlukan "Kuki: SameSite=Lax secara baku". - # about:home should be kept in English, as it refers to the the URI for # the internal default home page. experimental-features-abouthome-startup-cache = .label = Tembolok awal about:home experimental-features-abouthome-startup-cache-description = Tembolok untuk dokumen about:home awal yang dimuat secara baku pada saat memulai. Tujuan dari tembolok ini adalah untuk meningkatkan kinerja proses mulai. - # The title of the experiment should be kept in English as it may be referenced # by various online articles and is technical in nature. experimental-features-cookie-samesite-schemeful = .label = Kuki: SameSite Berskema experimental-features-cookie-samesite-schemeful-description = Perlakukan kuki dari domain sama, tetapi dengan skema berbeda (contoh: http://example.com dan https://example.com) sebagai situs silang dan bukan situs yang sama. Hal ini meningkatkan keamanan tetapi mengandung potensi kerusakan. - # "Service Worker" is an API name and is usually not translated. experimental-features-devtools-serviceworker-debugger-support = .label = Alat Pengembang: Debugging Service Worker # "Service Worker" is an API name and is usually not translated. experimental-features-devtools-serviceworker-debugger-support-description = Mengaktifkan dukungan eksperimental untuk Service Worker di panel Debugger. Fitur ini mungkin memperlambat Alat Pengembang dan meningkatkan penggunaan memori. - # WebRTC global mute toggle controls experimental-features-webrtc-global-mute-toggles = .label = Aktifkan/Nonaktifkan Kesenyapan WebRTC Global experimental-features-webrtc-global-mute-toggles-description = Tambahkan kontrol ke indikator berbagi global WebRTC yang memungkinkan pengguna menonaktfikan suara mikrofon dan umpan kamera secara global. - # Win32k Lockdown experimental-features-win32k-lockdown = .label = Win32k Lockdown - +experimental-features-win32k-lockdown-description = Nonaktifkan penggunaan API Win32k di tab browser. Memberikan peningkatan keamanan tetapi saat ini mungkin tidak stabil atau berpeluang glitch. (Hanya Windows) # JS JIT Warp project experimental-features-js-warp = .label = JavaScript JIT: Warp experimental-features-js-warp-description = Aktifkan Warp, sebuah proyek untuk meningkatkan kinerja JavaScript dan penggunaan memori. - # Fission is the name of the feature and should not be translated. experimental-features-fission = .label = Fission (Isolasi Situs) experimental-features-fission-description = Fission (isolasi situs) adalah fitur eksperimental di { -brand-short-name } untuk menyediakan lapisan pertahanan tambahan terhadap bug keamanan. Dengan mengisolasi masing-masing situs ke dalam proses terpisah, Fission mempersulit situs web berbahaya mendapatkan akses ke informasi laman lain yang Anda kunjungi. Ini adalah perubahan arsitektur besar-besaran pada { -brand-short-name } dan kami berterima kasih jika Anda menguji dan melaporkan masalah yang mungkin dialami. Untuk detail lebih lanjut, lihat wiki. - # Support for having multiple Picture-in-Picture windows open simultaneously experimental-features-multi-pip = .label = Dukungan Beberapa Gambar-dalam-Gambar experimental-features-multi-pip-description = Dukungan eksperimental untuk memungkinkan beberapa jendela Gambar-dalam-Gambar dibuka pada saat yang sama. - # Search during IME experimental-features-ime-search = .label = Bilah Alamat: Tampilkan hasil selama komposisi IME experimental-features-ime-search-description = IME (Input Method Editor) adalah alat yang memungkinkan Anda memasukkan simbol kompleks, seperti yang digunakan dalam bahasa tulis Asia Timur atau India, menggunakan papan ketik standar. Mengaktifkan eksperimen ini akan membuat panel alamat terbuka, menampilkan hasil pencarian dan saran, ketika menggunakan IME untuk memasukkan teks. Perhatikan bahwa IME mungkin menampilkan panel yang menutupi hasil bilah alamat, karena itu preferensi ini hanya disarankan bagi IME tidak menggunakan panel jenis ini. +# Firefox 100 +experimental-features-firefox-100 = + .label = String User-Agent { -brand-product-name } 100 +experimental-features-firefox-100-description = Jadikan { -brand-short-name } mengirim ke situs web string User-Agent yang berpura-pura menjadi { -brand-product-name } versi 100. Gunakan setelan ini untuk menguji apakah situs web akan rusak saat { -brand-short-name } mencapai nomor versi tiga digit. { -brand-product-name } 100 asli dijadwalkan akan dirilis pada Mei 2022, jadi mulailah menguji situs web Anda sekarang! diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/global/processTypes.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/global/processTypes.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/global/processTypes.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/global/processTypes.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -8,28 +8,24 @@ ## process-type-web = Konten Web - # process used to run privileged about pages, # such as about:home process-type-privilegedabout = Laman About dengan Izin Khusus - # process used to run privileged mozilla pages, # such as accounts.firefox.com process-type-privilegedmozilla = Konten Mozilla yang Diistimewakan - process-type-extension = Ekstensi - # process used to open file:// URLs process-type-file = Berkas Lokal - # process used to isolate webpages that requested special # permission to allocate large amounts of memory process-type-weblargeallocation = Alokasi Besar - # process used to isolate a webpage from other web pages # to improve security process-type-webisolated = Konten Web Terisolasi - +# process used to isolate a ServiceWorker to improve +# performance +process-type-webserviceworker = Pekerja Layanan Terisolasi # process preallocated; may change to other types process-type-prealloc = Teralokasikan @@ -37,12 +33,17 @@ ## Localization for Gecko process types defined in GeckoProcessTypes.h ## +process-type-default = Utama +process-type-tab = Tab # process used to communicate with the GPU for # graphics acceleration process-type-gpu = GPU - # process used to perform network operations process-type-socket = Soket +# process used to decode media +process-type-rdd = RDD +# process used to run some IPC actor in their own sandbox +process-type-utility = Aktor IPC dalam Kotak Pasir ## ## Other diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/global/run-from-dmg.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/global/run-from-dmg.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/global/run-from-dmg.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/global/run-from-dmg.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -9,6 +9,7 @@ ## user accepts. prompt-to-install-title = Selesaikan pemasangan { -brand-short-name }? +prompt-to-install-message = Selesaikan instalasi satu langkah ini untuk membantu agar { -brand-short-name } selalu mutakhir dan mencegah kehilangan data. { -brand-short-name } akan ditambahkan ke folder Applications dan Dock Anda. prompt-to-install-yes-button = Instal prompt-to-install-no-button = Jangan Instal diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/global/textActions.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/global/textActions.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/global/textActions.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/global/textActions.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -37,5 +37,20 @@ .key = A text-action-spell-no-suggestions = .label = Tidak Ada Saran Ejaan +text-action-spell-add-to-dictionary = + .label = Tambah ke Kamus + .accesskey = T +text-action-spell-undo-add-to-dictionary = + .label = Batalkan Penambahan ke Kamus + .accesskey = n +text-action-spell-check-toggle = + .label = Periksa Ejaan + .accesskey = j +text-action-spell-add-dictionaries = + .label = Tambah Kamus… + .accesskey = a +text-action-spell-dictionaries = + .label = Bahasa + .accesskey = B text-action-search-text-box-clear = .title = Bersihkan diff -Nru thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/printing/printUI.ftl thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/printing/printUI.ftl --- thunderbird-91.7.0+build2/l10n/id/toolkit/toolkit/printing/printUI.ftl 2022-03-07 21:39:03.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/id/toolkit/toolkit/printing/printUI.ftl 2022-04-15 07:54:04.000000000 +0000 @@ -5,15 +5,15 @@ printui-title = Cetak # Dialog title to prompt the user for a filename to save print to PDF. printui-save-to-pdf-title = Simpan sebagai - # Variables # $sheetCount (integer) - Number of paper sheets printui-sheets-count = { $sheetCount -> *[other] { $sheetCount } lembar kertas } - printui-page-range-all = Semua +printui-page-range-odd = Ganjil +printui-page-range-even = Genap printui-page-range-custom = Ubahsuai printui-page-range-label = Halaman printui-page-range-picker = @@ -21,29 +21,22 @@ printui-page-custom-range-input = .aria-label = Masukkan rentang halaman khusus .placeholder = mis. 2-6, 9, 12-16 - # Section title for the number of copies to print printui-copies-label = Salinan - printui-orientation = Orientasi printui-landscape = Mendatar printui-portrait = Tegak - # Section title for the printer or destination device to target printui-destination-label = Tujuan printui-destination-pdf-label = Simpan ke PDF - printui-more-settings = Pengaturan lainnya printui-less-settings = Beberapa pengaturan - printui-paper-size-label = Ukuran kertas: - # Section title (noun) for the print scaling options printui-scale = Skala printui-scale-fit-to-page-width = Sesuaikan dengan lebar halaman # Label for input control where user can set the scale percentage printui-scale-pcent = Skala - # Section title (noun) for the two-sided print options printui-two-sided-printing = Pencetakan dua sisi printui-two-sided-printing-off = Nonaktif @@ -51,7 +44,6 @@ printui-two-sided-printing-long-edge = Balik pada sisi panjang # Flip the sheet as if it were bound along its short edge. printui-two-sided-printing-short-edge = Balik pada sisi pendek - # Section title for miscellaneous print options printui-options = Opsi printui-headers-footers-checkbox = Cetak kepala dan kaki @@ -61,12 +53,20 @@ ## options to select between the original page, selected text only, or a version ## where the page is processed with "Reader View". +# The section title. +printui-source-label = Format +# Option for printing the original page. +printui-source-radio = Asli +# Option for printing just the content a user selected prior to printing. +printui-selection-radio = Pilihan +# Option for "simplifying" the page by printing the Reader View version. +printui-simplify-page-radio = Disederhanakan + ## printui-color-mode-label = Mode warna printui-color-mode-color = Warna printui-color-mode-bw = Hitam putih - printui-margins = Margin printui-margins-default = Baku printui-margins-min = Minimum @@ -85,23 +85,17 @@ printui-margins-custom-right = Kanan printui-margins-custom-right-inches = Kanan (inci) printui-margins-custom-right-mm = Kanan (mm) - printui-system-dialog-link = Cetak menggunakan dialog sistem… - printui-primary-button = Cetak printui-primary-button-save = Simpan printui-cancel-button = Batal printui-close-button = Tutup - printui-loading = Mempersiapkan Pratinjau - # Reported by screen readers and other accessibility tools to indicate that # the print preview has focus. printui-preview-label = .aria-label = Pratinjau Cetak - printui-pages-per-sheet = Halaman per lembar - # This is shown next to the Print button with an indefinite loading spinner # when the user prints a page and it is being sent to the printer. printui-print-progress-indicator = Mencetak… @@ -128,7 +122,6 @@ printui-error-invalid-scale = Skala harus berupa angka antara 10 dan 200 printui-error-invalid-margin = Masukkan margin yang valid untuk ukuran kertas yang dipilih. printui-error-invalid-copies = Salinan harus berupa angka antara 1 dan 10000. - # Variables # $numPages (integer) - Number of pages printui-error-invalid-range = Rentang harus berupa angka antara 1 dan { $numPages } diff -Nru thunderbird-91.7.0+build2/l10n/is/calendar/calendar/calendar-editable-item.ftl thunderbird-91.8.1+build1/l10n/is/calendar/calendar/calendar-editable-item.ftl --- thunderbird-91.7.0+build2/l10n/is/calendar/calendar/calendar-editable-item.ftl 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/calendar/calendar/calendar-editable-item.ftl 2022-04-15 07:54:11.000000000 +0000 @@ -6,6 +6,10 @@ .alt = Persónuvernd: Einkaatburður calendar-editable-item-privacy-icon-confidential = .alt = Persónuvernd: Birta aðeins tíma og dagsetningu +calendar-editable-item-recurrence = + .alt = Endurtekið +calendar-editable-item-recurrence-exception = + .alt = Undantekning frá endurtekningu calendar-editable-item-todo-icon-task = .alt = Verkefni calendar-editable-item-todo-icon-completed-task = diff -Nru thunderbird-91.7.0+build2/l10n/is/calendar/calendar/calendar-invitation-panel.ftl thunderbird-91.8.1+build1/l10n/is/calendar/calendar/calendar-invitation-panel.ftl --- thunderbird-91.7.0+build2/l10n/is/calendar/calendar/calendar-invitation-panel.ftl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/calendar/calendar/calendar-invitation-panel.ftl 2022-04-15 07:54:12.000000000 +0000 @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Variables: +# $organizer (String) - The participant that created the original invitation. +calendar-invitation-panel-intro = { $organizer } hefur boðið þér að: +# Variables: +# $summary (String) - A short summary or title of the event. +calendar-invitation-panel-title = { $summary } +calendar-invitation-panel-action-button = Vista +calendar-invitation-panel-accept-button = Já +calendar-invitation-panel-decline-button = Nei +calendar-invitation-panel-tentative-button = Kannski +calendar-invitation-panel-reply-status = * Þú hefur ekki ákveðið eða svarað ennþá +calendar-invitation-panel-prop-title-when = Hvenær: +calendar-invitation-panel-prop-title-location = Staðsetning: +# Variables: +# $dayOfWeek (String) - The day of the week for a given date. +# $date (String) - The date example: Tuesday, February 24, 2022. +calendar-invitation-datetime-date = { $dayOfWeek }, { $date } +# Variables: +# $time (String) - The time part of a datetime using the "short" timeStyle. +# $timezone (String) - The timezone info for the datetime. +calendar-invitation-datetime-time = { $time } ({ $timezone }) +calendar-invitation-panel-prop-title-attendees = Þátttakendur: +calendar-invitation-panel-prop-title-description = Lýsing: +# Variables: +# $partStat (String) - String indicating the participation status of an attendee. +calendar-invitation-panel-partstat-summary = + { $partStat -> + [ACCEPTED] { $count } já + [DECLINED] { $count } nei + [TENTATIVE] { $count } kannski + [NEEDS-ACTION] { $count } í bið + [TOTAL] { $count } þátttakendur + *[OTHER] { $count } aðrir + } diff -Nru thunderbird-91.7.0+build2/l10n/is/chat/imtooltip.properties thunderbird-91.8.1+build1/l10n/is/chat/imtooltip.properties --- thunderbird-91.7.0+build2/l10n/is/chat/imtooltip.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/chat/imtooltip.properties 2022-04-15 07:54:11.000000000 +0000 @@ -4,7 +4,7 @@ buddy.username=Notandanafn buddy.account=Aðgangur -contact.tags=Flokkar +contact.tags=Merki otr.tag=OTR-staða diff -Nru thunderbird-91.7.0+build2/l10n/is/chat/matrix.properties thunderbird-91.8.1+build1/l10n/is/chat/matrix.properties --- thunderbird-91.7.0+build2/l10n/is/chat/matrix.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/chat/matrix.properties 2022-04-15 07:54:12.000000000 +0000 @@ -242,3 +242,17 @@ # %2$S is the reason given why the verification was cancelled. message.verification.cancel2=%1$S hætti við staðfestinguna með ástæðunni: %2$S message.verification.done=Staðfestingu lokið. +message.decryptionError=Ekki tókst að afkóða innihald þessara skilaboða. Til að biðja um dulritunarlykla frá öðrum tækjum þínum skaltu hægrismella á þessi skilaboð. +message.decrypting=Afkóðar... +message.redacted=Skilaboðin voru ritstýrð. + +# Label in the message context menu +message.action.requestKey=Biðja aftur um lykla +message.action.redact=Ritstýra +message.action.report=Tilkynna skilaboð +message.action.retry=Reyna aftur að senda +message.action.cancel=Hætta við skilaboð + +# LOCALIZATION NOTE (error.*) +# These are strings shown as system messages when an action the user took fails. +error.sendMessageFailed=Villa kom upp við að senda skilaboðin þín "%1$S". diff -Nru thunderbird-91.7.0+build2/l10n/is/devtools/client/aboutdebugging.ftl thunderbird-91.8.1+build1/l10n/is/devtools/client/aboutdebugging.ftl --- thunderbird-91.7.0+build2/l10n/is/devtools/client/aboutdebugging.ftl 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/devtools/client/aboutdebugging.ftl 2022-04-15 07:54:11.000000000 +0000 @@ -63,7 +63,7 @@ about-debugging-sidebar-runtime-item-name-no-device = .title = { $displayName } # Text to show in the footer of the sidebar that links to a help page -# (currently: https://developer.mozilla.org/docs/Tools/about:debugging) +# (currently: https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/) about-debugging-sidebar-support = Stuðningur við villuleit # Text to show as the ALT attribute of a help icon that accompanies the help about # debugging link in the footer of the sidebar @@ -108,13 +108,13 @@ # USB section step by step guide about-debugging-setup-usb-step-plug-device = Tengja Android tækið við tölvuna þína. # Text shown in the USB section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_over_USB +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device about-debugging-setup-usb-troubleshoot = Ertu í vandræðum með að tengjast USB-tækinu? Úrræðaleit # Network section of the Setup page about-debugging-setup-network = .title = Netstaðsetning # Text shown in the Network section of the setup page with a link to troubleshoot connection errors. -# The link goes to https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Debugging_over_a_network +# The link goes to https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network about-debugging-setup-network-troubleshoot = Vandamál með að tengjast í gegnum netstaðsetningu? Úrræðaleit # Text of a button displayed after the network locations "Host" input. # Clicking on it will add the new network location to the list. @@ -157,9 +157,13 @@ about-debugging-runtime-processes = .name = Ferli # This string is displayed in the runtime page if the current configuration of the -# target runtime is incompatible with service workers. "Learn more" points to MDN. -# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible +# target runtime is incompatible with service workers. "Learn more" points to: +# https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#service-workers-not-compatible about-debugging-runtime-service-workers-not-compatible = Stilling vafrans þíns er ekki samhæfð við þjónustuferli (Service Workers). Frekari upplýsingar +# Displayed for runtime info in runtime pages. +# { $name } is brand name such as "Firefox Nightly" +# { $version } is version such as "64.0a1" +about-debugging-runtime-name = { $name } ({ $version }) # Text of a button displayed in Runtime pages for remote runtimes. # Clicking on the button will close the connection to the runtime. about-debugging-runtime-disconnect-button = Aftengja diff -Nru thunderbird-91.7.0+build2/l10n/is/devtools/client/debugger.properties thunderbird-91.8.1+build1/l10n/is/devtools/client/debugger.properties --- thunderbird-91.7.0+build2/l10n/is/devtools/client/debugger.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/devtools/client/debugger.properties 2022-04-15 07:54:11.000000000 +0000 @@ -160,6 +160,7 @@ # LOCALIZATION NOTE (eventListenersHeader1.placeholder): The placeholder text in # the event search input bar +eventListenersHeader1.placeholder=Sía eftir tegund atburðar # LOCALIZATION NOTE (domMutationHeader): The text to display in the # DOM Mutation Breakpoints header @@ -243,7 +244,7 @@ # LOCALIZATION NOTE (projectTextSearch.noResults): The center pane Text Search # message when the query did not match any text of all files in a project. -projectTextSearch.noResults=No results found +projectTextSearch.noResults=Engar niðurstöður fundust # LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search # for searching within a the currently opened files in the editor @@ -274,6 +275,7 @@ # LOCALIZATION NOTE (sourceSearch.resultsSummary2): Semi-colon list of plural forms. # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # Shows a summary of the number of matches for autocomplete +sourceSearch.resultsSummary2=#1 niðurstaða;#1 niðurstöður # LOCALIZATION NOTE (breakpointHeadingMenuItem.*): The text for all the elements # that are displayed in the breakpoint headings menu item popup. @@ -373,6 +375,7 @@ # LOCALIZATION NOTE (editor.searchResults1): Semi-colon list of plural forms. # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # Editor Search bar message to summarize the selected search result. e.g. 5 of 10 results. +editor.searchResults1=%d af #1 niðurstöðu;%d af #1 niðurstöðum # LOCALIZATION NOTE (editor.noResultsFound): Editor Search bar message # for when no results found. @@ -587,6 +590,18 @@ # LOCALIZATION NOTE (ignoreContextItem.unignore): Text associated # with the unignore context menu item +# LOCALIZATION NOTE (ignoreContextItem.ignoreLine): Text associated +# with the ignore line context menu item + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLine): Text associated +# with the unignore line context menu item + +# LOCALIZATION NOTE (ignoreContextItem.ignoreLines): Text associated +# with the ignore lines context menu item + +# LOCALIZATION NOTE (ignoreContextItem.unignoreLines): Text associated +# with the unignore lines context menu item + # LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated # with a mapped source. %S is replaced by the source map origin. sourceFooter.mappedSource=(From %S) @@ -679,6 +694,7 @@ # LOCALIZATION NOTE (welcome.search2): The center pane welcome panel's # search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on # a mac we use the unicode character. +welcome.search2=%S Fara í skrá # LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's # search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on @@ -688,6 +704,7 @@ # LOCALIZATION NOTE (welcome.findInFiles2): The center pane welcome panel's # search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on # a mac we use the unicode character. +welcome.findInFiles2=%S Finna í skrám # LOCALIZATION NOTE (welcome.allShortcuts): The label to open the modal of # shortcuts, displayed in the welcome panel. @@ -918,6 +935,7 @@ # LOCALIZATION NOTE (shortcuts.functionSearch2): text describing # keyboard shortcut action for function search +shortcuts.functionSearch2=Finna aðgerð # LOCALIZATION NOTE (shortcuts.buttonName): text describing # keyboard shortcut button text diff -Nru thunderbird-91.7.0+build2/l10n/is/devtools/client/netmonitor.properties thunderbird-91.8.1+build1/l10n/is/devtools/client/netmonitor.properties --- thunderbird-91.7.0+build2/l10n/is/devtools/client/netmonitor.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/devtools/client/netmonitor.properties 2022-04-15 07:54:11.000000000 +0000 @@ -708,39 +708,49 @@ # LOCALIZATION NOTE (netmonitor.search.toolbar.inputPlaceholder): This is the label # displayed in the search toolbar for the search input as the placeholder. +netmonitor.search.toolbar.inputPlaceholder=Finna í tilföngum… # LOCALIZATION NOTE (netmonitor.search.toolbar.close): This is the label # displayed in the search toolbar to close the search panel. +netmonitor.search.toolbar.close=Loka leitarspjaldinu # LOCALIZATION NOTE (netmonitor.search.toolbar.clear): This is the label # displayed in the search toolbar to clear the search panel. +netmonitor.search.toolbar.clear=Hreinsa leitarniðurstöður # LOCALIZATION NOTE (netmonitor.search.toolbar.caseSensitive): This is the label # displayed in the search toolbar to do a case sensitive search. +netmonitor.search.toolbar.caseSensitive=Næmt fyrir stafstöðu # LOCALIZATION NOTE (netmonitor.search.status.labels.fetching): This is the label # displayed in the search results status bar when status is set to fetching. +netmonitor.search.status.labels.fetching=Leita… # LOCALIZATION NOTE (netmonitor.search.status.labels.canceled): This is the label # displayed in the search results status bar when status is set to cancelled. +netmonitor.search.status.labels.canceled=Hætt við leit. # LOCALIZATION NOTE (netmonitor.search.status.labels.done): This is the label # displayed in the search results status bar when status is set to done. # %1$S is the number of matching lines in search results (netmonitor.search.status.labels.matchingLines) # %2$S is the number of files in which matching lines were found (netmonitor.search.status.labels.fileCount) +netmonitor.search.status.labels.done=Leit lokið. %1$S %2$S. # LOCALIZATION NOTE (netmonitor.search.status.labels.matchingLines): Semi-colon list of plural forms. # This is the label displayed in the search results status bar showing matching lines found. # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # #1 is the number of matching lines found +netmonitor.search.status.labels.matchingLines=Fann #1 samsvarandi línu;Fann #1 samsvarandi línur # LOCALIZATION NOTE (netmonitor.search.status.labels.fileCount): Semi-colon list of plural forms. # This is the label displayed in the search results status bar showing file count # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # #1 is the number of files in which matching lines were found +netmonitor.search.status.labels.fileCount=in #1 skrá;in #1 skrár # LOCALIZATION NOTE (netmonitor.search.status.labels.error): This is the label # displayed in the search results status bar when status is set to error. +netmonitor.search.status.labels.error=Villa í leit. # LOCALIZATION NOTE (netmonitor.toolbar.requestBlocking): This is the tooltip displayed # over the toolbar's Request Blocking buttonn @@ -775,6 +785,7 @@ # LOCALIZATION NOTE (netmonitor.actionbar.search): This is the label displayed # in the action bar's search tab +netmonitor.actionbar.search=Leita # LOCALIZATION NOTE (netmonitor.actionbar.HTTPCustomRequest): This is the label displayed # in the action bar's edit and resend tab @@ -885,6 +896,7 @@ # LOCALIZATION NOTE (netmonitor.toolbar.search.key): This is the # shortcut key to toggle the search panel +netmonitor.toolbar.search.key=CmdOrCtrl+Shift+F # LOCALIZATION NOTE (netmonitor.toolbar.copy.key): This is the # shortcut key to copy a selected request url from the network table @@ -919,6 +931,7 @@ # LOCALIZATION NOTE (netmonitor.toolbar.search): This is the tooltip label displayed # in the network toolbar for the search button. +netmonitor.toolbar.search=Leita # LOCALIZATION NOTE (netmonitor.toolbar.HTTPCustomRequest): This is the tooltip label displayed # in the network toolbar for the new HTTP Custom Request button. @@ -1345,10 +1358,28 @@ # above the query string entry in the custom request form netmonitor.custom.query=Query String: +# LOCALIZATION NOTE (netmonitor.custom.urlParameters): This is the label displayed +# above the query string entry in the custom request form + # LOCALIZATION NOTE (netmonitor.custom.headers): This is the label displayed # above the request headers entry in the custom request form netmonitor.custom.headers=Request Headers: +# LOCALIZATION NOTE (netmonitor.custom.newRequestHeaders): This is the label displayed +# above the request headers entry in the new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.name): This is the placeholder displayed +# on the input on the headers and query params on new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.placeholder.value): This is the placeholder displayed +# on the input on the headers and query params on new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.postBody): This is the label displayed +# above the request body entry in the new custom request form + +# LOCALIZATION NOTE (netmonitor.custom.postBody.placeholder): This is the placeholder displayed +# on the textarea body in the new custom request form + # LOCALIZATION NOTE (netmonitor.custom.postData): This is the label displayed # above the request body entry in the custom request form netmonitor.custom.postData=Request Body: @@ -1361,6 +1392,12 @@ # on the button which cancels and closes the custom request form netmonitor.custom.cancel=Cancel +# LOCALIZATION NOTE (netmonitor.custom.clear): This is the label displayed +# on the button which clears the content of the new custom request panel + +# LOCALIZATION NOTE (netmonitor.custom.removeItem): This is the +# tooltip shown over the remove button for headers and query params item + # LOCALIZATION NOTE (netmonitor.backButton): This is the label displayed # on the button which exists the performance statistics view netmonitor.backButton=Back diff -Nru thunderbird-91.7.0+build2/l10n/is/devtools/client/shared.properties thunderbird-91.8.1+build1/l10n/is/devtools/client/shared.properties --- thunderbird-91.7.0+build2/l10n/is/devtools/client/shared.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/devtools/client/shared.properties 2022-04-15 07:54:11.000000000 +0000 @@ -6,3 +6,20 @@ # of a node or image, like 100×200. dimensions=%S×%S +# LOCALIZATION NOTE (boxModelSize.accessibleLabel): This is used to read the +# dimensions of a node by a screen reader. This helps communicate +# the visual information in a more explicit form. Example: +# Size: Width 100, height 200. +boxModelSize.accessibleLabel=Stærð: Breidd %1$S, hæð %2$S + +# LOCALIZATION NOTE (boxModelInfo.accessibleLabel): This is used to read the +# dimensions and position of a node by a screen reader. This helps communicate +# the visual information in a more explicit form. Example: +# Dimensions: Width 100, height 200, position static. +boxModelInfo.accessibleLabel=Mál: Breidd %1$S, hæð %2$S, staðsetning %3$S + +# LOCALIZATION NOTE (boxModelEditable.accessibleLabel): The string spoken by +# screen readers for each button in the box model view that opens that property +# for editing. %1$S is the property displayed in the tooltip when hovering. +# %2$S is the value that is visually displayed. +# Example: margin-left: 0. diff -Nru thunderbird-91.7.0+build2/l10n/is/devtools/shared/styleinspector.properties thunderbird-91.8.1+build1/l10n/is/devtools/shared/styleinspector.properties --- thunderbird-91.7.0+build2/l10n/is/devtools/shared/styleinspector.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/devtools/shared/styleinspector.properties 2022-04-15 07:54:11.000000000 +0000 @@ -111,6 +111,7 @@ # LOCALIZATION NOTE (rule.filterStyles.placeholder): This is the placeholder that # goes in the search box when no search term has been entered. +rule.filterStyles.placeholder=Sía stíla # LOCALIZATION NOTE (rule.addRule.tooltip): This is the tooltip shown when # hovering the `Add new rule` button in the rules view toolbar. diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/css.properties thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/css.properties --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/css.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/css.properties 2022-04-15 07:54:11.000000000 +0000 @@ -40,4 +40,4 @@ PEExpectedNoneOrURLOrFilterFunction=Bjóst við ‘none’, URL, eða síu fall en fann ‘%1$S’. TooLargeDashedRadius=Ramma radíus er of stór fyrir ‘dashed’ stíl (hámark er 100000px). Teiknað sem gegnheilt. -TooLargeDottedRadius=Ramma radíus er of stór fyrir ‘dotted’ stíl (hámark er 100000px). Teiknað sem gegnheilt. +TooLargeDottedRadius=Radíus jaðars er of stór fyrir ‘dotted’ stíl (hámark er 100000px). Myndgert sem gegnheilt. diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/htmlparser.properties thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/htmlparser.properties --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/htmlparser.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/htmlparser.properties 2022-04-15 07:54:11.000000000 +0000 @@ -10,11 +10,11 @@ EncLateMeta=Stafasett HTML skjalsins fannst ekki eftir að athugað var fremstu 1024 bæti skráarinnar. Ef skjalið er skoðað í vafra sem er stilltur öðruvísi, verður síðan endurnýjuð sjálfvirkt. Færa þarf stafasett skilgreiningu í fyrstu 1024 bæti skráarinnar. EncLateMetaReload=Síðan var endurnýjuð, vegna þess að stafasett HTML skjalsins fannst ekki eftir að athugað var fremstu 1024 bæti skráarinnar. Færa þarf stafasett skilgreiningu í fyrstu 1024 bæti skráarinnar. EncLateMetaTooLate=Stafasett skjalsins fannst of seint til að hægt væri að nota það. Færa þarf stafasett skilgreiningu í fyrstu 1024 bæti skráarinnar. -EncMetaUnsupported=Skilgreint var stafasett með meta tagi fyrir HTML skjalið sem er ekki hægt að nota. Skilgreiningin var hunsuð. +EncMetaUnsupported=Skilgreint var stafasett með meta-merki fyrir HTML skjalið sem er ekki hægt að nota. Skilgreiningin var hunsuð. EncProtocolUnsupported=Skilgreint var stafasett á samskiptalagi sem er ekki hægt að nota. Skilgreiningin var hunsuð. EncBomlessUtf16=Fann UTF-16 kóðað Basic Latin-only texta án þess að vera með bætaröðunartákni og án þess að vera með skilgreiningu á samskiptalagi. Að kóða innihaldið í UTF-16 er óskilvirkt og ætti að vera skilgreint hvort sem er. -EncMetaUtf16=Fann meta tag sem skilgreindi stafasett sem UTF-16. Túlkaði þetta sem UTF-8 skilgreiningu í staðinn. -EncMetaUserDefined=Lýsitag var notað til að skilgreina stafakóðun sem x-user-defined. Þetta var túlkað sem windows-1252 skilgreining í staðinn fyrir samhæfni við úreltar leturgerðir. Þetta vefsvæði ætti að færa sig yfir í Unicode. +EncMetaUtf16=Fann meta-merki sem skilgreindi stafasett sem UTF-16. Túlkaði þetta sem UTF-8 skilgreiningu í staðinn. +EncMetaUserDefined=Lýsimerki var notað til að skilgreina stafakóðun sem x-user-defined. Þetta var túlkað sem windows-1252 skilgreining í staðinn fyrir samhæfni við úreltar leturgerðir. Þetta vefsvæði ætti að færa sig yfir í Unicode. # The audience of the following message isn't the author of the document but other people debugging browser behavior. EncSpeculationFail2022=Upphaf skjalsins var endurtekið, vegna þess að ISO-2022-JP er stafakóðun sem ekki samræmist ASCII. @@ -47,7 +47,7 @@ errBadCharBeforeAttributeNameLt=Fékk “<” en bjóst við nafni eigindis. Líkleg ástæða: Vantar “>” fyrir framan. errEqualsSignBeforeAttributeName=Fékk “=” en bjóst við nafni eigindis. Líkleg ástæða: Vantar nafn eigindis. errBadCharAfterLt=Rangur stafur eftir “<”. Líkleg ástæða: Óbreytt “<”. Prófaðu að umrita það sem “<”. -errLtGt=Fékk “<>”. Líkleg ástæða: Óbreytt “<” (umrita sem “<”) eða rangt ritað byrjunartag. +errLtGt=Fékk “<>”. Líkleg ástæða: Óbreytt “<” (umrita sem “<”) eða rangt ritað byrjunarmerki. errProcessingInstruction=Fékk “”. Hunsa tag. -errEofInTagName=Fékk endi á skrá þegar búist var við nafni tags. Hunsa tag. -errEofInEndTag=Endir á skrá inn í endatagi. Hunsa tag. +errEofInAttributeValue=Endir á skrá inn í gildi eigindis. Hunsa merkið. +errEofInAttributeName=Endir á skrá inni í nafni eigindis. Hunsa merkið. +errEofWithoutGt=Fékk endi á skrá án þess að fyrra merki hafi endað með “>”. Hunsa merkið. +errEofInTagName=Fékk endi á skrá þegar búist var við nafni merkis. Hunsa merkið. +errEofInEndTag=Endir á skrá inni í endamerki. Hunsa merkið. errEofAfterLt=Endir á skrá eftir “<”. errNcrOutOfRange=Stafgildi fyrir utan leyfileg mörk Unicode bils. errNcrUnassigned=Stafgildi verður að staf sem er fastsett sem óúthlutanlegt. @@ -86,10 +86,10 @@ errNoSpaceBetweenDoctypePublicKeywordAndQuote=Ekkert bil á milli doctype “PUBLIC” og tilvitnunarstaf. # Tree builder errors -errStrayStartTag2=Auka byrjunartag “%1$S”. -errStrayEndTag=Auka endatag “%1$S”. -errUnclosedElements=Fékk endatag “%1$S”, en ennþá voru opin einindi. -errUnclosedElementsImplied=Endatag “%1$S” var óbeint skilgreint, en ennþá voru opin einindi. +errStrayStartTag2=Auka byrjunarmerki “%1$S”. +errStrayEndTag=Auka endamerki “%1$S”. +errUnclosedElements=Fékk endamerki “%1$S”, en ennþá voru opin einindi. +errUnclosedElementsImplied=Endamerki “%1$S” var óbeint skilgreint, en ennþá voru opin einindi. errUnclosedElementsCell=Töflureit var óbeint lokað, en einindi voru samt opin. errStrayDoctype=Auka doctype. errAlmostStandardsDoctype=Næstum því venjulegur doctype hamur. Bjóst við “”. @@ -121,7 +121,7 @@ errNoElementToCloseButEndTagSeen=Ekkert “%1$S” einindi í gildissviði en fékk “%1$S” endatag. errHtmlStartTagInForeignContext=HTML byrjunartag “%1$S” í óþekktu nafnarými. errNoTableRowToClose=Engin töfluröð til að loka. -errNonSpaceInTable=Stafur sem er ekki bil á vitlausum stað innan í töflu. +errNonSpaceInTable=Stafur sem er ekki bil á röngum stað innan í töflu. errUnclosedChildrenInRuby=Opin undireinindi í “ruby”. errStartTagSeenWithoutRuby=Fékk byrjunartag “%1$S” án þess að “ruby” einindi væri opið. errSelfClosing=Sjálflokandi tákn (“/>”) notað í HTML tagi sem má ekki vera tómt. Hunsa skástrikið og nota það sem byrjunartag. diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/layout_errors.properties thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/layout_errors.properties --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/layout_errors.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/layout_errors.properties 2022-04-15 07:54:11.000000000 +0000 @@ -6,11 +6,12 @@ ImageMapCircleWrongNumberOfCoords=Eigindið “coords” fyrir tagið er ekki á “center-x,center-y,radius” sniði. ImageMapCircleNegativeRadius=Eigindið “coords” fyrir tagið er með neikvæðan radíus. ImageMapPolyWrongNumberOfCoords=Eigindið “coords” fyrir tagið er ekki á “x1,y1,x2,y2 …” sniði. -ImageMapPolyOddNumberOfCoords=Eigindið “coords” fyrir tagið vantar seinasta “y” hnitið (rétt snið er “x1,y1,x2,y2 …”). +ImageMapPolyOddNumberOfCoords=Eigindið “coords” fyrir merkið vantar seinasta “y” hnitið (rétt snið er “x1,y1,x2,y2 …”). TablePartRelPosWarning=Afstæð staðsetning á röðum í töflu og hópum er núna orðið virkt. Þetta vefsvæði þyrfti hugsanlega að uppfæra þar sem það þarfnast þess að þessi eiginleiki hafi ekki áhrif. ScrollLinkedEffectFound2=Þessi síða virðist nota skrun tengt staðsetningar áhrif. Þetta virkar líklega illa með ósamstilltri hliðrun; kíktu á https://developers.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects fyrir meiri upplýsingar og taktu þátt í umræðunum þar um tengd tól og eiginleika! + ## LOCALIZATION NOTE(CompositorAnimationWarningContentTooLargeArea): ## %1$S is an integer value of the area of the frame ## %2$S is an integer value of the area of a limit based on the viewport size @@ -36,3 +37,13 @@ CompositorAnimationWarningOpacityFrameInactive=Ekki er hægt að keyra hreyfimyndir á compositor þar sem ramminn var ekki merktur sem virkur fyrir ‘’opacity’ hreyfimynd CompositorAnimationWarningHasRenderingObserver=Ekki er hægt að keyra hreyfimynd á compositor þar sem einindi er með teiknifylgjendur (-moz-element eða SVG clipping/masking) +## LOCALIZATION NOTE: Do not translate zoom, calc(), "transform", "transform-origin: 0 0" + +## LOCALIZATION NOTE(PrincipalWritingModePropagationWarning): +## Do not translate , , CSS, "writing-mode", "direction", "text-orientation", :root, and "The Principal Writing Mode" because they are technical terms. + +## LOCALIZATION NOTE(ScrollAnchoringDisabledInContainer): +## %1$S is an integer value with the total number of adjustments +## %2$S is a floating point value with the average distance adjusted +## %3$S is a floating point value with the total adjusted distance + diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/xmlparser.properties thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/xmlparser.properties --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/layout/xmlparser.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/layout/xmlparser.properties 2022-04-15 07:54:11.000000000 +0000 @@ -9,9 +9,9 @@ 4 = ekki vel sniðið 5 = óuppgefið teikn 6 = hluti af staf -7 = misstilling á tagi +7 = ósamsvarandi merki 8 = tvöfalt eigindi -9 = rusl á eftir document tagi +9 = rusl á eftir document-merki 10 = ólögleg tilvísunar færibreyta 11 = óskilgreint einindi 12 = endurkvæm eininda tilvísun diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/mathml/mathml.properties thunderbird-91.8.1+build1/l10n/is/dom/chrome/mathml/mathml.properties --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/mathml/mathml.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/mathml/mathml.properties 2022-04-15 07:54:11.000000000 +0000 @@ -3,7 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. InvalidChild=Ógildur kóði: <%1$S> er ekki leyft undir <%2$S>. -ChildCountIncorrect=Ógildur kóði: Rangur fjöldi af börnum fyrir <%1$S/> tag. +ChildCountIncorrect=Ógildur kóði: Rangur fjöldi af afleiðum fyrir <%1$S/> merki. DuplicateMprescripts=Ógildur kóði: Fleiri en eitt í . # LOCALIZATION NOTE: The first child of is the base, that is the element to which scripts are attached. NoBase=Ógildur kóði: Bjóst við nákvæmlega einu Base einindi í . Fann ekkert. diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/netError.dtd thunderbird-91.8.1+build1/l10n/is/dom/chrome/netError.dtd --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/netError.dtd 2022-03-07 21:39:09.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/netError.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -8,13 +8,13 @@ -Þótt svæðið virðist vera gilt, getur vafrinn ekki tengst því.

    • Gæti verið að vefsvæðið sé niðri tímabundið? Reyndu aftur seinna.
    • Geturðu ekki tengst við önnur svæði? Athugaðu netstillingar tölvu.
    • Er tölvan þín eða net varið af eldvegg eða milliþjóni? Rangar stillingar geta haft áhrif á netvafra.
    "> +Þótt svæðið virðist vera gilt, getur vafrinn ekki tengst því.

    • Gæti verið að vefsvæðið sé niðri tímabundið? Reyndu aftur seinna.
    • Geturðu ekki tengst við önnur vefsvæði? Athugaðu netstillingar tölvu.
    • Er tölvan þín eða net varið af eldvegg eða milliþjóni? Rangar stillingar geta haft áhrif á netvafra.
    "> Umbeðið veffang bað um ákveðna gátt (t.d. mozilla.org:80 fyrir gátt 80 á mozilla.org) sem er venjulega notað fyrir eitthvað annað að vafra. Vafrinn hefur lokað á beiðnina þér til verndar.

    "> -Vafrinn fann ekki vefþjóninn fyrir þetta netfang.

    • Slóstu inn rangt netfang? (t.d. ww.mozilla.org í staðinn fyrir www.mozilla.org)
    • Ertu viss um að þetta vefsvæði sé til? Vefsvæðið gæti verið útrunnið.
    • Geturðu tengst öðrum svæðum? Athugaðu netstillingar og DNS stillingar tölvu.
    • Er tölvan varin af eldvegg eða milliþjóni? Rangar stillingar geta haft áhrif á vafra.
    "> +Vafrinn fann ekki vefþjóninn fyrir þetta netfang.

    • Slóstu inn rangt netfang? (t.d. ww.mozilla.org í staðinn fyrir www.mozilla.org)
    • Ertu viss um að þetta vefsvæði sé til? Vefsvæðið gæti verið útrunnið.
    • Geturðu tengst öðrum vefsvæðum? Athugaðu netstillingar og DNS stillingar tölvu.
    • Er tölvan varin af eldvegg eða milliþjóni? Rangar stillingar geta haft áhrif á vafra.
    ">
  • Gæti verið að hluturinn hafi verið endurnefndur, fjarlægður, eða færður til?
  • Er stafsetningarvilla, hástafaritun, eða annarskonar stafsetningarvilla í vistfanginu?
  • Hefurðu nægar aðgangsheimildir fyrir hlutinn?
  • "> @@ -29,7 +29,7 @@ Innslegið vistfang er ekki á viðurkenndu sniði. Athugaðu hvort slegið var inn rangt og reyndu aftur.

    "> -Vafrinn gat tengst, en tenging var rofin meðan verið var að senda upplýsingar. Reyndu aftur.

    • Geturðu ekki tengst við önnur svæði? Athugaðu netstillingar tölvu.
    • Ennþá vandamál? Hafðu samband við kerfisstjóra eða netaðila fyrir hjálp.
    "> +Vafrinn gat tengst, en tenging var rofin meðan verið var að senda upplýsingar. Reyndu aftur.

    • Geturðu ekki tengst við önnur vefsvæði? Athugaðu netstillingar tölvu.
    • Ennþá vandamál? Hafðu samband við kerfisstjóra eða netþjónustu til að fá aðstoð.
    "> Umbeðið skjal er ekki til í skyndiminni vafrans.

    • Vegna öryggisástæðna, nær vafrinn ekki sjálfkrafa aftur í viðkvæm skjöl.
    • Smelltu á reyna aftur til að ná aftur í skjalið frá vefsvæðinu.
    "> @@ -47,16 +47,16 @@ Net rofnaði meðan verið var að semja um tengingu. Reynið aftur.

    "> -Umbeðið vefsvæði svaraði ekki tengingu og vafrinn hætti að bíða eftir svari.

    • Getur verið að svæðið sé í mikilli notkun eða sé niðri tímabundið? Reyndu aftur seinna.
    • Geturðu haft samband við önnur svæði? Athugaðu nettengingu tölvunnar.
    • Er tölvan eða netið varið af eldvegg eða milliþjóni? Rangar stillingar geta haft áhrif á vafra.
    • Ennþá vandamál? Hafðu samband við kerfistjóra eða netaðila fyrir hjálp.
    "> +Umbeðið vefsvæði svaraði ekki tengingu og vafrinn hætti að bíða eftir svari.

    • Getur verið að svæðið sé í mikilli notkun eða sé niðri tímabundið? Reyndu aftur seinna.
    • Geturðu haft samband við önnur vefsvæði? Athugaðu nettengingu tölvunnar.
    • Er tölvan eða netið varið af eldvegg eða milliþjóni? Rangar stillingar geta haft áhrif á vafra.
    • Ennþá vandamál? Hafðu samband við kerfistjóra eða netþjónustu til að fá aðstoð.
    "> Umbeðið vistfang skilgreinir samskiptareglu (t.d. wxyz://) sem vafrinn kannast ekki við, þannig að vafrinn getur ekki tengst við vefsvæðið.

    • Ertu að reyna að tengjast myndefni eða annarskonar gagnaþjónustum? athugaðu á vefsvæðinu hvort þú þurfir fleiri hluti.
    • Sumar samskiptareglur þarfnast forrita eða tengiforrita frá þriðja aðila áður en vafrinn getur þekkt þær.
    "> -Vafrinn er stilltur til að nota milliþjóna, en milliþjónn hafnaði tengingu.

    • Eru vafra stillingar milliþjóns rétt stilltar? Athugaðu stillingarnar og reyndu aftur.
    • Leyfir milliþjónn tengingar frá þínu neti?
    • Ennþá vandamál? Hafðu samband við kerfistjóra eða netaðila fyrir hjálp.
    "> +Vafrinn er stilltur til að nota milliþjóna, en milliþjónn hafnaði tengingu.

    • Eru vafra stillingar milliþjóns rétt stilltar? Athugaðu stillingarnar og reyndu aftur.
    • Leyfir milliþjónn tengingar frá þínu neti?
    • Ennþá vandamál? Hafðu samband við kerfistjóra eða netþjónustu til að fá aðstoð.
    "> -Vafrinn er stilltur til að nota milliþjóna, en milliþjónn fannst ekki.

    • Eru vafra stillingar milliþjóns rétt stilltar? Athugaðu stillingarnar og reyndu aftur.
    • Leyfir milliþjónn tengingar frá þínu neti?
    • Ennþá vandamál? Hafðu samband við kerfistjóra eða netaðila fyrir hjálp.
    "> +Vafrinn er stilltur til að nota milliþjóna, en milliþjónn fannst ekki.

    • Eru vafra stillingar milliþjóns rétt stilltar? Athugaðu stillingarnar og reyndu aftur.
    • Leyfir milliþjónn tengingar frá þínu neti?
    • Ennþá vandamál? Hafðu samband við kerfistjóra eða netþjónustu til að fá aðstoð.
    "> Vafrinn hefur hætt að reyna að ná í umbeðið atriði. Vefsvæðið er að endursenda beiðnina á þann hátt að því mun aldrei ljúka.

    • Hefurðu lokað á eða gert vefkökur óvirkar frá þessu vefsvæði?
    • ATHUGAÐU: Ef þú velur að taka á móti vefkökum frá þessu vefsvæði og það lagar ekki vandamálið, er netþjónninn sjálfur líklega rangt stilltur en ekki tölvan þín.
    "> diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/security/caps.properties thunderbird-91.8.1+build1/l10n/is/dom/chrome/security/caps.properties --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/security/caps.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/security/caps.properties 2022-04-15 07:54:11.000000000 +0000 @@ -3,7 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. CheckLoadURIError = Öryggisvilla: Efni á %S má ekki hlaða eða tengjast við %S. CheckSameOriginError = Öryggisvilla: Efni á %S má ekki hlaða gögnum frá %S. -ExternalDataError = Öryggisvilla: Innihald frá %S reyndi að hlaða inn %S, en það má ekki þegar það verið er að nota það sem mynd.\u00A0 +ExternalDataError = Öryggisvilla: Efni frá %S reyndi að hlaða inn %S, en það má ekki hlaða inn fjartengdum gögnum þegar verið er að nota það sem mynd. CreateWrapperDenied = Aðgangi hafnað fyrir að búa til umgjörð utan um hlut af klasa %S CreateWrapperDeniedForOrigin = Aðgangi hafnað fyrir <%2$S> til að búa til umgjörð fyrir hlut af klasa %1$S diff -Nru thunderbird-91.7.0+build2/l10n/is/dom/chrome/security/csp.properties thunderbird-91.8.1+build1/l10n/is/dom/chrome/security/csp.properties --- thunderbird-91.7.0+build2/l10n/is/dom/chrome/security/csp.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/dom/chrome/security/csp.properties 2022-04-15 07:54:11.000000000 +0000 @@ -45,7 +45,7 @@ ignoringSrcForStrictDynamic = Hunsa “%1$S” innan í script-src: ‘strict-dynamic’ er skilgreint # LOCALIZATION NOTE (ignoringStrictDynamic): # %1$S is the ignored src -ignoringStrictDynamic = Hunsa “%1$S” (Aðeins með stuðning inna í script-src).\u0020 +ignoringStrictDynamic = Hunsa “%1$S” (Aðeins með stuðning innan í script-src). # LOCALIZATION NOTE (strictDynamicButNoHashOrNonce): # %1$S is the csp directive that contains 'strict-dynamic' # 'strict-dynamic' should not be localized @@ -74,7 +74,7 @@ # %1$S is the URL of the blocked resource load. blockAllMixedContent = Loka á óörugga beiðni ‘%1$S’. # LOCALIZATION NOTE (ignoringDirectiveWithNoValues): -# %1$S is the name of a CSP directive that requires additional values (e.g., 'require-sri-for') +# %1$S is the name of a CSP directive that requires additional values ignoringDirectiveWithNoValues = Hunsa ‘%1$S‘ þar sem það inniheldur engar breytur. # LOCALIZATION NOTE (ignoringReportOnlyDirective): # %1$S is the directive that is ignored in report-only mode. @@ -83,7 +83,10 @@ # %1$S is the name of the src that is ignored. # %2$S is the name of the directive that causes the src to be ignored. IgnoringSrcBecauseOfDirective=Hunsa ‘%1$S’ vegna ‘%2$S’ skipunar. - +# LOCALIZATION NOTE (IgnoringSourceWithinDirective): +# %1$S is the ignored src +# %2$S is the directive which supports src + # CSP Errors: # LOCALIZATION NOTE (couldntParseInvalidSource): # %1$S is the source that could not be parsed diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/communicator/utilityOverlay.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/communicator/utilityOverlay.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/communicator/utilityOverlay.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/communicator/utilityOverlay.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -6,7 +6,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/AccountManager.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/AccountManager.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/AccountManager.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/AccountManager.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -13,7 +13,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/AccountWizard.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/AccountWizard.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/AccountWizard.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/AccountWizard.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -4,7 +4,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/activity.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/activity.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/activity.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/activity.properties 2022-04-15 07:54:11.000000000 +0000 @@ -58,7 +58,7 @@ # Message actions that show up in activity manager # LOCALIZATION NOTE (deletedMessages2): #1 number of messages, #2 folder name -deletedMessages2=Eyddi #1 pósti frá #2;Eyddi #1 póstum frá #2 +deletedMessages2=Eyddi #1 pósti úr #2;Eyddi #1 póstum úr #2 # LOCALIZATION NOTE (movedMessages): #1 number of messages, #2 and #3: folder names movedMessages=Færði #1 póst frá #2 til #3;Færði #1 pósta frá #2 til #3 # LOCALIZATION NOTE (copiedMessages): #1 number of messages, #2 and #3: folder names diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/abCard.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/abCard.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/abCard.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/abCard.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -31,7 +31,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/abContactsPanel.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/abContactsPanel.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/abContactsPanel.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/abContactsPanel.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -7,7 +7,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/abMainWindow.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/abMainWindow.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/abMainWindow.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/abMainWindow.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -9,7 +9,7 @@ - + @@ -56,7 +56,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/addressBook.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/addressBook.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/addressbook/addressBook.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/addressbook/addressBook.properties 2022-04-15 07:54:12.000000000 +0000 @@ -28,7 +28,7 @@ cardRequiredDataMissingMessage=Þú verður að slá inn að minnsta kosti eitt af þessu:\nTölvupóstfang, Skírnarnafn, Eftirnafn, Birtingarnafn, Fyrirtæki. cardRequiredDataMissingTitle=Vantar nauðsynlegar upplýsingar incorrectEmailAddressFormatMessage=Aðal-tölvupóstfang verður að vera á sniðinu notandi@hýsing. -incorrectEmailAddressFormatTitle=Vitlaust snið á tölvupóstfangi +incorrectEmailAddressFormatTitle=Rangt snið á tölvupóstfangi viewListTitle=Póstlisti: %S mailListNameExistsTitle=Póstlisti er þegar til diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/baseMenuOverlay.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/baseMenuOverlay.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/baseMenuOverlay.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/baseMenuOverlay.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -11,7 +11,7 @@ - + @@ -23,7 +23,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/devtools/dbgserver.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/devtools/dbgserver.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/devtools/dbgserver.dtd 2022-03-07 21:39:09.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/devtools/dbgserver.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -2,7 +2,7 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - - + + + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/devtools/dbgserver.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/devtools/dbgserver.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/devtools/dbgserver.properties 2022-03-07 21:39:09.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/devtools/dbgserver.properties 2022-04-15 07:54:11.000000000 +0000 @@ -2,14 +2,14 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -options.stop.label=Stop Developer Tools Server -options.start.label=Start Developer Tools Server +options.stop.label=Stöðva þróunartækjaþjón +options.start.label=Ræsa þróunartækjaþjón -options.connected.label=#1 Client Connected;#1 Clients Connected -options.connected.tooltip=The developer tools server is running and there are clients connected. -options.listening.label=Listening -options.listening.tooltip=The developer tools server is running and waiting for connections. -options.idle.label=Not Running -options.idle.tooltip=The developer tools server is not running. You can start it from this dialog. -options.unsupported.label=Unsupported -options.unsupported.tooltip=There was an error loading the built-in developer tools server. Make sure it is packaged and check your error console for messages. +options.connected.label=#1 biðlaraforrit tengt;#1 biðlaraforrit tengd +options.connected.tooltip=Þróunartækjaþjónninn er í gangi og það eru biðlaraforrit tengd. +options.listening.label=Hlustandi +options.listening.tooltip=Þróunartækjaþjónninn er í gangi og bíður eftir tengingum. +options.idle.label=Ekki í gangi +options.idle.tooltip=Þróunartækjaþjónninn er ekki í gangi. Þú getur ræst hann úr þessum glugga. +options.unsupported.label=Óstutt +options.unsupported.tooltip=Villa kom upp við að hlaða inn innbyggða þróunarverkfæraþjóninum. Gakktu úr skugga um að honum sé pakkað og athugaðu skilaboð á villuskjánum þínum. diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/FilterEditor.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/FilterEditor.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/FilterEditor.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/FilterEditor.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -44,7 +44,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/filter.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/filter.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/filter.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/filter.properties 2022-04-15 07:54:11.000000000 +0000 @@ -90,7 +90,7 @@ filterAction5=henda umræðu filterAction6=fylgjast með umræðu filterAction7=stjörnumerkt -filterAction8=flokkað +filterAction8=merkt filterAction9=svarað filterAction10=áframsent filterAction11=stöðva keyrslu @@ -99,7 +99,7 @@ filterAction14=ruslpósts stig filterAction15=meginmál náð í frá POP3 póstþjóni filterAction16=afritað í möppu -filterAction17=flokkað +filterAction17=merkt filterAction18=hunsaður undirumræða filterAction19=merkt sem ólesið # LOCALIZATION NOTE(filterAutoNameStr) diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/glodaComplete.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/glodaComplete.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/glodaComplete.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/glodaComplete.properties 2022-04-15 07:54:11.000000000 +0000 @@ -5,7 +5,7 @@ # LOCALIZATION NOTE (glodaComplete.messagesTagged.label): The label used # in the autocomplete widget to refer to a query for all messages tagged # by a particular tag (replacing #1). -glodaComplete.messagesTagged.label=Flokkaður póstur: #1 +glodaComplete.messagesTagged.label=Skilaboð merkt: #1 # LOCALIZATION NOTE (glodaComplete.messagesMentioning.label): The label used # in the autocomplete widget to refer to a search for all messages mentioning diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/glodaFacetView.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/glodaFacetView.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/glodaFacetView.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/glodaFacetView.properties 2022-04-15 07:54:11.000000000 +0000 @@ -41,7 +41,7 @@ # LOCALIZATION NOTE(glodaFacetView.constraints.query.contact.label): # The label to display to describe when our base query was on messages # tagged with a specific tag. The tag is displayed following the label. -glodaFacetView.constraints.query.tagged.label=flokkað: +glodaFacetView.constraints.query.tagged.label=merkt: # LOCALIZATION NOTE (glodaFacetView.facets.mode.top.listAllLabel): The label to diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/gloda.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/gloda.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/gloda.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/gloda.properties 2022-04-15 07:54:11.000000000 +0000 @@ -127,15 +127,15 @@ # do not do anything clever with gmail, so this is independent of gmail labels # This may change in the future, but it's a safe bet it's not happening on # Thunderbird's side prior to 3.0. -gloda.message.attr.tag.facetNameLabel=Flokkar +gloda.message.attr.tag.facetNameLabel=Merki gloda.message.attr.tag.noneLabel=Ekkert gloda.message.attr.tag.includeLabel=merkt sem eitthvað af: gloda.message.attr.tag.excludeLabel=ekki merkt: gloda.message.attr.tag.remainderLabel=önnur merki: -gloda.message.attr.tag.mustMatchLabel=verður að vera flokkaður #1 -gloda.message.attr.tag.cantMatchLabel=má ekki vera flokkaður #1 -gloda.message.attr.tag.mustMatchSomeLabel=verður að vera flokkaður -gloda.message.attr.tag.mustMatchNoneLabel=má ekki vera flokkaður +gloda.message.attr.tag.mustMatchLabel=verður að vera merkt #1 +gloda.message.attr.tag.cantMatchLabel=má ekki vera merkt #1 +gloda.message.attr.tag.mustMatchSomeLabel=verður að vera merkt +gloda.message.attr.tag.mustMatchNoneLabel=má ekki vera merkt # LOCALIZATION NOTE (gloda.message.attr.star.*): Stores whether the message is # starred or not, as indicated by a pretty star icon. In the past, the icon diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/imAccountWizard.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/imAccountWizard.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/imAccountWizard.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/imAccountWizard.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -2,7 +2,7 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/importDialog.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/importDialog.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/importDialog.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/importDialog.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -3,14 +3,6 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - - - - - - - - + + + + + + + - + - - + + - - + + - - + + - + - + - - - - - - - - + + + + + + + + - + - - + + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/junkMailInfo.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/junkMailInfo.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/junkMailInfo.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/junkMailInfo.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -8,4 +8,4 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/localMsgs.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/localMsgs.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/localMsgs.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/localMsgs.properties 2022-04-15 07:54:11.000000000 +0000 @@ -90,9 +90,9 @@ pop3TempServerError=Tímabundin villa frá %S við að sækja ný skilaboð. \ Aðgerðin verður endurtekin við næstu athugun á nýjum skilaboðum. -copyingMessagesStatus=Afrita %S af %S póstum til %S +copyingMessagesStatus=Afrita %S af %S póstum í %S -movingMessagesStatus=Færi %S af %S póstum til %S +movingMessagesStatus=Færi %S af %S póstum í %S # Status - pop3 server or folder busy # LOCALIZATION NOTE (pop3ServerBusy): Do not translate the word "%S" below. diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/composeMsgs.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/composeMsgs.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/composeMsgs.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/composeMsgs.properties 2022-04-15 07:54:12.000000000 +0000 @@ -57,7 +57,7 @@ errorAttachingFile=Upp kom villa við að setja inn viðhengi %S. Athugaðu að þú hafir aðgang að skrá. ## LOCALIZATION NOTE (incorrectSmtpGreeting): argument %s is the Outgoing server (SMTP) greeting -incorrectSmtpGreeting=Upp kom villa við að senda póst: Póstþjónn sendi vitlaust svar: %s. +incorrectSmtpGreeting=Upp kom villa við að senda póst: Póstþjónn sendi rangt svar: %s. ## LOCALIZATION NOTE (errorSendingRcptCommand): argument %1$S is the Outgoing server (SMTP) response, argument %2$S is the intended message recipient. errorSendingRcptCommand=Upp kom villa við að senda póst. Póstþjónn svaraði: \n%1$S.\n Athugaðu mótttakanda pósts "%2$S" og reyndu aftur. diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertSource.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertSource.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertSource.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertSource.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -4,7 +4,7 @@ - + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertTOC.dtd thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertTOC.dtd --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertTOC.dtd 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/EditorInsertTOC.dtd 2022-04-15 07:54:11.000000000 +0000 @@ -2,15 +2,15 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - - - - - - - - - - - + + + + + + + + + + + + diff -Nru thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/editor.properties thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/editor.properties --- thunderbird-91.7.0+build2/l10n/is/mail/chrome/messenger/messengercompose/editor.properties 2022-03-07 21:39:10.000000000 +0000 +++ thunderbird-91.8.1+build1/l10n/is/mail/chrome/messenger/messengercompose/editor.properties 2022-04-15 07:54:11.000000000 +0000 @@ -35,7 +35,7 @@ CheckSpelling=Yfirfara stafsetningu InputError=Villa Alert=Aðvörun -CantEditFramesetMsg=Composer getur ekki breytt HTML römmum, eða síðum með innsettum römmum. Fyrir ramma, reyndu að breyta hverri síðu með rammanum sér. Fyrir síður með iframe, vistaðu afrit af síðunni og fjarlægðu