diff -Nru thunderbird-115.3.0+build2/browser/config/version_display.txt thunderbird-115.3.1+build1/browser/config/version_display.txt --- thunderbird-115.3.0+build2/browser/config/version_display.txt 2023-09-26 18:55:41.000000000 +0000 +++ thunderbird-115.3.1+build1/browser/config/version_display.txt 2023-09-29 10:32:44.000000000 +0000 @@ -1 +1 @@ -115.3.0esr +115.3.1esr diff -Nru thunderbird-115.3.0+build2/browser/config/version.txt thunderbird-115.3.1+build1/browser/config/version.txt --- thunderbird-115.3.0+build2/browser/config/version.txt 2023-09-26 18:55:41.000000000 +0000 +++ thunderbird-115.3.1+build1/browser/config/version.txt 2023-09-29 10:32:44.000000000 +0000 @@ -1 +1 @@ -115.3.0 +115.3.1 diff -Nru thunderbird-115.3.0+build2/BUILDID thunderbird-115.3.1+build1/BUILDID --- thunderbird-115.3.0+build2/BUILDID 2023-09-26 18:57:38.000000000 +0000 +++ thunderbird-115.3.1+build1/BUILDID 2023-09-29 10:34:15.000000000 +0000 @@ -1 +1 @@ -20230926115257 \ No newline at end of file +20230928194049 \ No newline at end of file diff -Nru thunderbird-115.3.0+build2/comm/calendar/base/modules/Ical.jsm thunderbird-115.3.1+build1/comm/calendar/base/modules/Ical.jsm --- thunderbird-115.3.0+build2/comm/calendar/base/modules/Ical.jsm 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/calendar/base/modules/Ical.jsm 2023-09-29 10:32:58.000000000 +0000 @@ -12,7 +12,7 @@ * upstream first. * * Current ical.js git revision: - * https://github.com/darktrojan/ical.js/commit/8d6c9047424fde8f78062a52da57e1a6fab8d2e7 + * https://github.com/darktrojan/ical.js/commit/0f1af2444b82708bb3a0a6b05d834884dedd8109 */ var EXPORTED_SYMBOLS = ["ICAL", "unwrap", "unwrapSetter", "unwrapSingle", "wrapGetter"]; @@ -7182,7 +7182,14 @@ this.initialized = options.initialized || false; if (!this.initialized) { - this.init(); + try { + this.init(); + } catch (e) { + // Init may error if there are no possible recurrence instances from + // the rule, but we don't want to bubble this error up. Instead, we + // create an empty iterator. + this.completed = true; + } } }, @@ -7256,7 +7263,17 @@ } if (this.rule.freq == "YEARLY") { - for (;;) { + // Some yearly recurrence rules may be specific enough to not actually + // occur on a yearly basis, e.g. the 29th day of February or the fifth + // Monday of a given month. The standard isn't clear on the intended + // behavior in these cases, but `libical` at least will iterate until it + // finds a matching year. + // CAREFUL: Some rules may specify an occurrence that can never happen, + // e.g. the first Monday of April so long as it falls on the 15th + // through the 21st. Detecting these is non-trivial, so ensure that we + // stop iterating at some point. + var untilYear = this.rule.until ? this.rule.until.year : 20000; + while (this.last.year <= untilYear) { this.expand_year_days(this.last.year); if (this.days.length > 0) { break; @@ -7264,6 +7281,10 @@ this.increment_year(this.rule.interval); } + if (this.days.length == 0) { + throw new Error("No possible occurrences"); + } + this._nextByYearDay(); } @@ -7354,15 +7375,12 @@ * @return {ICAL.Time} */ next: function icalrecur_iterator_next() { - var before = (this.last ? this.last.clone() : null); - if ((this.rule.count && this.occurrence_number >= this.rule.count) || (this.rule.until && this.last.compare(this.rule.until) > 0)) { - - //XXX: right now this is just a flag and has no impact - // we can simplify the above case to check for completed later. this.completed = true; + } + if (this.completed) { return null; } @@ -7372,7 +7390,6 @@ return this.last; } - var valid; do { valid = 1; diff -Nru thunderbird-115.3.0+build2/comm/.gecko_rev.yml thunderbird-115.3.1+build1/comm/.gecko_rev.yml --- thunderbird-115.3.0+build2/comm/.gecko_rev.yml 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/.gecko_rev.yml 2023-09-29 10:32:58.000000000 +0000 @@ -1,8 +1,8 @@ --- GECKO_BASE_REPOSITORY: https://hg.mozilla.org/mozilla-unified GECKO_HEAD_REPOSITORY: https://hg.mozilla.org/releases/mozilla-esr115 -GECKO_HEAD_REF: FIREFOX_115_3_0esr_BUILD1 -GECKO_HEAD_REV: 17bedcda2f5c28b7fbc136d300bdbbf04f382e00 +GECKO_HEAD_REF: FIREFOX_115_3_1esr_RELEASE +GECKO_HEAD_REV: 749617c4473c65f8aebb2e3254777ae99dc17cce ### For comm-central # GECKO_BASE_REPOSITORY: https://hg.mozilla.org/mozilla-unified diff -Nru thunderbird-115.3.0+build2/comm/mail/config/version_display.txt thunderbird-115.3.1+build1/comm/mail/config/version_display.txt --- thunderbird-115.3.0+build2/comm/mail/config/version_display.txt 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mail/config/version_display.txt 2023-09-29 10:32:58.000000000 +0000 @@ -1 +1 @@ -115.3.0 +115.3.1 diff -Nru thunderbird-115.3.0+build2/comm/mail/config/version.txt thunderbird-115.3.1+build1/comm/mail/config/version.txt --- thunderbird-115.3.0+build2/comm/mail/config/version.txt 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mail/config/version.txt 2023-09-29 10:32:58.000000000 +0000 @@ -1 +1 @@ -115.3.0 +115.3.1 diff -Nru thunderbird-115.3.0+build2/comm/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js thunderbird-115.3.1+build1/comm/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js --- thunderbird-115.3.0+build2/comm/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js 2023-09-29 10:32:58.000000000 +0000 @@ -370,12 +370,7 @@ if (self.getSavedDraftOptions(mimeMsg)) { obtainedDraftFlagsObj.value = true; } - if (self.draftSubjectEncrypted) { - self.setOriginalSubject(msgHdr.subject, msgHdr.flags, false); - } updateEncryptionDependencies(); - } else if (EnigmailURIs.isEncryptedUri(msgUri)) { - self.setOriginalSubject(msgHdr.subject, msgHdr.flags, false); } } } catch (ex) { @@ -506,85 +501,6 @@ return true; }, - /** - * Updates the subject displayed in the #msgSubject element of the compose - * window. Sets prefixes such as "Re" depending on the value gMsgCompose.type. - * - * @param {string} subject The subject for the message. - * @param {number} flags The nsIMsgHdr flags for the message, used to detect - * HasRe on drafts. - * @param {boolean} forceSetting If true, the subject is always updated - * otherwise it is only updated for the following nsIMsgCompTypes: Draft, - * Template,EditTemplate,ForwardInline,ForwardAttachement or EditAsNew. - */ - setOriginalSubject(subject, flags, forceSetting) { - const CT = Ci.nsIMsgCompType; - let subjElem = document.getElementById("msgSubject"); - let prefix = ""; - let isReply = false; - - if (!subjElem) { - return; - } - - switch (gMsgCompose.type) { - case CT.ForwardInline: - case CT.ForwardAsAttachment: - prefix = - Services.prefs.getStringPref("mail.forward_subject_prefix") + ": "; - break; - case CT.Draft: - isReply = Boolean(flags & Ci.nsMsgMessageFlags.HasRe); - break; - case CT.Reply: - case CT.ReplyAll: - case CT.ReplyToSender: - case CT.ReplyToGroup: - case CT.ReplyToSenderAndGroup: - case CT.ReplyToList: - isReply = true; - } - - if (isReply) { - if (!subject.startsWith("Re: ")) { - prefix = "Re: "; - } - } - - let doSetSubject = forceSetting; - switch (gMsgCompose.type) { - case CT.Draft: - case CT.Template: - case CT.EditTemplate: - case CT.ForwardInline: - case CT.ForwardAsAttachment: - case CT.EditAsNew: - doSetSubject = true; - break; - } - - if (doSetSubject) { - subject = jsmime.headerparser.decodeRFC2047Words(subject, "utf-8"); - - if (subjElem.value == "Re: " + subject) { - return; - } - - let newSubj = prefix + subject; - - if ( - newSubj !== subjElem.value || - newSubj !== gMsgCompose.compFields.subject - ) { - gMsgCompose.compFields.subject = newSubj; - subjElem.value = newSubj; - if (typeof subjElem.oninput === "function") { - subjElem.oninput(); - } - } - } - }, - composeOpen() { EnigmailLog.DEBUG( "enigmailMsgComposeOverlay.js: Enigmail.msg.composeOpen\n" diff -Nru thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/browser_editDraftTemplate.js thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/browser_editDraftTemplate.js --- thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/browser_editDraftTemplate.js 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/browser_editDraftTemplate.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +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/. */ - -"use strict"; - -/** - * Tests that drafts and templates get the appropriate security properties - * when opened. - */ - -var { open_compose_new_mail, setup_msg_contents } = ChromeUtils.import( - "resource://testing-common/mozmill/ComposeHelpers.jsm" -); - -var { - be_in_folder, - get_about_3pane, - get_special_folder, - mc, - right_click_on_row, - select_click_row, -} = ChromeUtils.import( - "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" -); -var { OpenPGPTestUtils } = ChromeUtils.import( - "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" -); - -var { MailServices } = ChromeUtils.import( - "resource:///modules/MailServices.jsm" -); - -let aliceAcct; -let aliceIdentity; -let draftsFolder; -let templatesFolder; - -/** - * Helper function to wait for a compose window to get opened. - * - * @returns The opened window. - */ -async function waitForComposeWindow() { - return BrowserTestUtils.domWindowOpened(null, async win => { - await BrowserTestUtils.waitForEvent(win, "load"); - return ( - win.document.documentURI === - "chrome://messenger/content/messengercompose/messengercompose.xhtml" - ); - }); -} - -function clearFolder(folder) { - return new Promise(resolve => { - let msgs = [...folder.msgDatabase.enumerateMessages()]; - - folder.deleteMessages( - msgs, - null, - true, - false, - { OnStopCopy: resolve }, - false - ); - }); -} - -add_setup(async function () { - aliceAcct = MailServices.accounts.createAccount(); - aliceAcct.incomingServer = MailServices.accounts.createIncomingServer( - "alice", - "openpgp.example", - "pop3" - ); - aliceIdentity = MailServices.accounts.createIdentity(); - aliceIdentity.email = "alice@openpgp.example"; - aliceAcct.addIdentity(aliceIdentity); - - let [id] = await OpenPGPTestUtils.importPrivateKey( - window, - new FileUtils.File( - getTestFilePath( - "data/keys/alice@openpgp.example-0xf231550c4f47e38e-secret.asc" - ) - ) - ); - - Assert.ok(id, "private key imported"); - - aliceIdentity.setUnicharAttribute("openpgp_key_id", id.split("0x").join("")); - - draftsFolder = await get_special_folder( - Ci.nsMsgFolderFlags.Drafts, - true, - aliceAcct.incomingServer.localFoldersServer - ); - - templatesFolder = await get_special_folder( - Ci.nsMsgFolderFlags.Templates, - true, - aliceAcct.incomingServer.localFoldersServer - ); -}); - -/** - * Create draft, make sure the sec properties are as they should after - * opening. - */ -add_task(async function testDraftSec() { - await be_in_folder(draftsFolder); - await doTestSecState(true, false); // draft, not secure - await doTestSecState(true, true); // draft, secure -}); - -/** - * Create template, make sure the sec properties are as they should after - * opening. - */ -add_task(async function testTemplSec() { - await be_in_folder(templatesFolder); - await doTestSecState(false, false); // template, not secure - await doTestSecState(false, true); // template, secure -}); - -/** - * Drafts/templates are stored encrypted before sent. Test that when composing - * and the reopening, the correct encryption states get set. - */ -async function doTestSecState(isDraft, secure) { - // Make sure to compose from alice. - let inbox = aliceAcct.incomingServer.rootFolder.getFolderWithFlags( - Ci.nsMsgFolderFlags.Inbox - ); - await be_in_folder(inbox); - - let cwc = open_compose_new_mail(); - let type = isDraft ? "draft" : "template"; - let theFolder = isDraft ? draftsFolder : templatesFolder; - setup_msg_contents( - cwc, - "test@example.invalid", - `test ${type}; secure=${secure}`, - `This is a ${type}; secure=${secure}` - ); - info(`Testing ${type}; secure=${secure}`); - - if (secure) { - // Tick "Require encryption". - // Encryption and signing should get turned on. - await OpenPGPTestUtils.toggleMessageEncryption(cwc.window); - } - - if (isDraft) { - cwc.window.SaveAsDraft(); - } else { - cwc.window.SaveAsTemplate(); - } - - await TestUtils.waitForCondition( - () => !cwc.window.gSaveOperationInProgress && !cwc.window.gWindowLock, - "timeout waiting for saving to finish." - ); - - info(`Saved as ${type} with secure=${secure}`); - cwc.window.close(); - - await be_in_folder(theFolder); - select_click_row(0); - - info(`Will open the ${type}`); - let draftWindowPromise = waitForComposeWindow(); - select_click_row(0); - await right_click_on_row(0); - - let about3Pane = get_about_3pane(); - let mailContext = about3Pane.document.getElementById("mailContext"); - if (isDraft) { - mailContext.activateItem( - about3Pane.document.getElementById("mailContext-editDraftMsg") - ); - } else { - mailContext.activateItem( - about3Pane.document.getElementById("mailContext-newMsgFromTemplate") - ); - } - - // The double click on col 4 (the subject) should bring up compose window - // for editing this draft. - - let draftWindow = await draftWindowPromise; - - info(`Checking security props in the UI...`); - - // @see setEncSigStatusUI() - if (!secure) { - // Wait some to make sure it won't (soon) be showing. - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(resolve => setTimeout(resolve, 100)); - } - draftWindow.close(); - clearFolder(theFolder); -} - -registerCleanupFunction(async function () { - MailServices.accounts.removeAccount(aliceAcct, true); - await OpenPGPTestUtils.removeKeyById("0xf231550c4f47e38e", true); -}); diff -Nru thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/browser.ini thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/browser.ini --- thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/browser.ini 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/browser.ini 2023-09-29 10:32:58.000000000 +0000 @@ -9,7 +9,6 @@ support-files = data/** [browser_collectKeys.js] -[browser_editDraftTemplate.js] [browser_keyWizard.js] [browser_openPGPDrafts.js] [browser_perm_decrypt.js] diff -Nru thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/composition/browser_editDraftTemplate.js thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/composition/browser_editDraftTemplate.js --- thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/composition/browser_editDraftTemplate.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/composition/browser_editDraftTemplate.js 2023-09-29 10:32:58.000000000 +0000 @@ -0,0 +1,221 @@ +/* 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/. */ + +"use strict"; + +/** + * Tests that drafts and templates get the appropriate security properties + * when opened. + */ + +var { open_compose_new_mail, setup_msg_contents } = ChromeUtils.import( + "resource://testing-common/mozmill/ComposeHelpers.jsm" +); + +var { + be_in_folder, + get_about_3pane, + get_special_folder, + mc, + right_click_on_row, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +var { OpenPGPTestUtils } = ChromeUtils.import( + "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" +); + +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +let aliceAcct; +let aliceIdentity; +let draftsFolder; +let templatesFolder; + +/** + * Helper function to wait for a compose window to get opened. + * + * @returns The opened window. + */ +async function waitForComposeWindow() { + return BrowserTestUtils.domWindowOpened(null, async win => { + await BrowserTestUtils.waitForEvent(win, "load"); + return ( + win.document.documentURI === + "chrome://messenger/content/messengercompose/messengercompose.xhtml" + ); + }); +} + +function clearFolder(folder) { + return new Promise(resolve => { + let msgs = [...folder.msgDatabase.enumerateMessages()]; + + folder.deleteMessages( + msgs, + null, + true, + false, + { OnStopCopy: resolve }, + false + ); + }); +} + +add_setup(async function () { + aliceAcct = MailServices.accounts.createAccount(); + aliceAcct.incomingServer = MailServices.accounts.createIncomingServer( + "alice", + "openpgp.example", + "pop3" + ); + aliceIdentity = MailServices.accounts.createIdentity(); + aliceIdentity.email = "alice@openpgp.example"; + aliceAcct.addIdentity(aliceIdentity); + + let [id] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/alice@openpgp.example-0xf231550c4f47e38e-secret.asc" + ) + ) + ); + + Assert.ok(id, "private key imported"); + + aliceIdentity.setUnicharAttribute("openpgp_key_id", id.split("0x").join("")); + + draftsFolder = await get_special_folder( + Ci.nsMsgFolderFlags.Drafts, + true, + aliceAcct.incomingServer.localFoldersServer + ); + + templatesFolder = await get_special_folder( + Ci.nsMsgFolderFlags.Templates, + true, + aliceAcct.incomingServer.localFoldersServer + ); +}); + +/** + * Create draft, make sure the sec properties are as they should after + * opening. + */ +add_task(async function testDraftSec() { + await be_in_folder(draftsFolder); + await doTestSecState(true, false); // draft, not secure + await doTestSecState(true, true); // draft, secure +}); + +/** + * Create template, make sure the sec properties are as they should after + * opening. + */ +add_task(async function testTemplSec() { + await be_in_folder(templatesFolder); + await doTestSecState(false, false); // template, not secure + await doTestSecState(false, true); // template, secure +}); + +/** + * Drafts/templates are stored encrypted before sent. Test that when composing + * and the reopening, the correct encryption states get set. + */ +async function doTestSecState(isDraft, secure) { + // Make sure to compose from alice. + let inbox = aliceAcct.incomingServer.rootFolder.getFolderWithFlags( + Ci.nsMsgFolderFlags.Inbox + ); + await be_in_folder(inbox); + + let cwc = open_compose_new_mail(); + let type = isDraft ? "draft" : "template"; + let theFolder = isDraft ? draftsFolder : templatesFolder; + let subject = `test ${type}; 🤐; secure=${secure}`; + setup_msg_contents( + cwc, + "test@example.invalid", + subject, + `This is a ${type}; secure=${secure}` + ); + info(`Testing ${type}; secure=${secure}`); + + if (secure) { + // Tick "Require encryption". + // Encryption and signing should get turned on. + await OpenPGPTestUtils.toggleMessageEncryption(cwc.window); + } + + if (isDraft) { + cwc.window.SaveAsDraft(); + } else { + cwc.window.SaveAsTemplate(); + } + + await TestUtils.waitForCondition( + () => !cwc.window.gSaveOperationInProgress && !cwc.window.gWindowLock, + "timeout waiting for saving to finish." + ); + + info(`Saved as ${type} with secure=${secure}`); + cwc.window.close(); + + await be_in_folder(theFolder); + select_click_row(0); + + info(`Will open the ${type}`); + let draftWindowPromise = waitForComposeWindow(); + select_click_row(0); + await right_click_on_row(0); + + let about3Pane = get_about_3pane(); + let mailContext = about3Pane.document.getElementById("mailContext"); + if (isDraft) { + mailContext.activateItem( + about3Pane.document.getElementById("mailContext-editDraftMsg") + ); + } else { + mailContext.activateItem( + about3Pane.document.getElementById("mailContext-newMsgFromTemplate") + ); + } + + let draftWindow = await draftWindowPromise; + + Assert.equal( + draftWindow.document.getElementById("msgSubject").value, + subject, + "subject should be decrypted" + ); + + info(`Checking security props in the UI...`); + + if (!secure) { + // Wait some to make sure it won't (soon) be showing. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(resolve => setTimeout(resolve, 100)); + Assert.ok( + !draftWindow.document.getElementById("button-encryption").checked, + "should not use encryption" + ); + } else { + await TestUtils.waitForCondition( + () => draftWindow.document.getElementById("button-encryption").checked, + "waited for encryption to get turned on" + ); + } + + draftWindow.close(); + clearFolder(theFolder); +} + +registerCleanupFunction(async function () { + MailServices.accounts.removeAccount(aliceAcct, true); + await OpenPGPTestUtils.removeKeyById("0xf231550c4f47e38e", true); +}); diff -Nru thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/composition/browser.ini thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/composition/browser.ini --- thunderbird-115.3.0+build2/comm/mail/test/browser/openpgp/composition/browser.ini 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mail/test/browser/openpgp/composition/browser.ini 2023-09-29 10:32:58.000000000 +0000 @@ -18,5 +18,6 @@ skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH [browser_composeSwitchIdentity.js] skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH +[browser_editDraftTemplate.js] [browser_expiredKey.js] skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH diff -Nru thunderbird-115.3.0+build2/comm/mailnews/base/src/nsMsgAccountManager.cpp thunderbird-115.3.1+build1/comm/mailnews/base/src/nsMsgAccountManager.cpp --- thunderbird-115.3.0+build2/comm/mailnews/base/src/nsMsgAccountManager.cpp 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mailnews/base/src/nsMsgAccountManager.cpp 2023-09-29 10:32:58.000000000 +0000 @@ -3046,45 +3046,6 @@ uint32_t folderFlags; folder->GetFlags(&folderFlags); - // Find any virtual folders that search `parent`, and add `folder` to them. - if (!(folderFlags & nsMsgFolderFlags::Virtual)) { - nsTObserverArray>::ForwardIterator iter( - m_virtualFolderListeners); - RefPtr listener; - - while (iter.HasMore()) { - listener = iter.GetNext(); - if (listener->m_folderWatching == parent) { - nsCOMPtr db; - nsCOMPtr dbFolderInfo; - listener->m_virtualFolder->GetDBFolderInfoAndDB( - getter_AddRefs(dbFolderInfo), getter_AddRefs(db)); - - nsCString searchURI; - dbFolderInfo->GetCharProperty(kSearchFolderUriProp, searchURI); - - // "normalize" searchURI so we can search for |folderURI|. - if (!searchURI.IsEmpty()) { - searchURI.Insert('|', 0); - searchURI.Append('|'); - } - nsCString folderURI; - folder->GetURI(folderURI); - - int32_t index = searchURI.Find(folderURI); - if (index == kNotFound) { - searchURI.Cut(0, 1); - searchURI.Append(folderURI); - dbFolderInfo->SetCharProperty(kSearchFolderUriProp, searchURI); - nsCOMPtr obs = - mozilla::services::GetObserverService(); - obs->NotifyObservers(listener->m_virtualFolder, - "search-folders-changed", nullptr); - } - } - } - } - bool addToSmartFolders = false; folder->IsSpecialFolder(nsMsgFolderFlags::Inbox | nsMsgFolderFlags::Templates | @@ -3169,6 +3130,53 @@ } } + // Find any virtual folders that search `parent`, and add `folder` to them. + if (!(folderFlags & nsMsgFolderFlags::Virtual)) { + nsTObserverArray>::ForwardIterator iter( + m_virtualFolderListeners); + RefPtr listener; + + while (iter.HasMore()) { + listener = iter.GetNext(); + if (listener->m_folderWatching == parent) { + nsCOMPtr db; + nsCOMPtr dbFolderInfo; + listener->m_virtualFolder->GetDBFolderInfoAndDB( + getter_AddRefs(dbFolderInfo), getter_AddRefs(db)); + + uint32_t vfFolderFlag; + dbFolderInfo->GetUint32Property("searchFolderFlag", 0, &vfFolderFlag); + if (addToSmartFolders && vfFolderFlag && + !(vfFolderFlag & nsMsgFolderFlags::Trash)) { + // Don't add folders of one type to the unified folder of another + // type, unless it's the Trash unified folder. + continue; + } + nsCString searchURI; + dbFolderInfo->GetCharProperty(kSearchFolderUriProp, searchURI); + + // "normalize" searchURI so we can search for |folderURI|. + if (!searchURI.IsEmpty()) { + searchURI.Insert('|', 0); + searchURI.Append('|'); + } + nsCString folderURI; + folder->GetURI(folderURI); + + int32_t index = searchURI.Find(folderURI); + if (index == kNotFound) { + searchURI.Cut(0, 1); + searchURI.Append(folderURI); + dbFolderInfo->SetCharProperty(kSearchFolderUriProp, searchURI); + nsCOMPtr obs = + mozilla::services::GetObserverService(); + obs->NotifyObservers(listener->m_virtualFolder, + "search-folders-changed", nullptr); + } + } + } + } + // need to make sure this isn't happening during loading of virtualfolders.dat if (folderFlags & nsMsgFolderFlags::Virtual && !m_loadingVirtualFolders) { // When a new virtual folder is added, need to create a db Listener for it. @@ -3306,7 +3314,16 @@ // do the right thing. nsCOMPtr parent; aFolder->GetParent(getter_AddRefs(parent)); - return OnFolderAdded(parent, aFolder); + nsresult rv = OnFolderAdded(parent, aFolder); + NS_ENSURE_SUCCESS(rv, rv); + + // This folder has one of the smart folder flags. + // Remove it from any other smart folders it might've been included in + // because of the flags of its ancestors. + RemoveFolderFromSmartFolder( + aFolder, (nsMsgFolderFlags::SpecialUse & ~nsMsgFolderFlags::Queue) & + ~newValue); + return NS_OK; } RemoveFolderFromSmartFolder(aFolder, smartFlagsChanged); diff -Nru thunderbird-115.3.0+build2/comm/mailnews/base/test/unit/test_virtualFolders3.js thunderbird-115.3.1+build1/comm/mailnews/base/test/unit/test_virtualFolders3.js --- thunderbird-115.3.0+build2/comm/mailnews/base/test/unit/test_virtualFolders3.js 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mailnews/base/test/unit/test_virtualFolders3.js 2023-09-29 10:32:58.000000000 +0000 @@ -10,10 +10,12 @@ "resource:///modules/VirtualFolderWrapper.jsm" ); -add_task(function () { +let rootFolder; + +add_setup(function () { MailServices.accounts.createLocalMailAccount(); let account = MailServices.accounts.accounts[0]; - let rootFolder = account.incomingServer.rootFolder; + rootFolder = account.incomingServer.rootFolder; rootFolder.QueryInterface(Ci.nsIMsgLocalMailFolder); // Listen to folder events for debugging purposes. @@ -60,19 +62,32 @@ }, Ci.nsIFolderListener.all ); +}); - // Test each of the folder types. - - subtest(rootFolder, "Inbox"); - subtest(rootFolder, "Drafts"); - subtest(rootFolder, "Templates"); - subtest(rootFolder, "SentMail"); - subtest(rootFolder, "Archive"); - subtest(rootFolder, "Junk"); - subtest(rootFolder, "Trash"); +// Test each of the folder types. +add_task(function testInbox() { + subtest("Inbox"); +}); +add_task(function testDrafts() { + subtest("Drafts"); +}); +add_task(function testTemplates() { + subtest("Templates"); +}); +add_task(function testSentMail() { + subtest("SentMail"); +}); +add_task(function testArchive() { + subtest("Archive"); +}); +add_task(function testJunk() { + subtest("Junk"); +}); +add_task(function testTrash() { + subtest("Trash"); }); -function subtest(rootFolder, flag) { +function subtest(flag) { // Create a virtual folder. This is very similar to the code in about3Pane.js. let virtualFolder = rootFolder.createLocalSubfolder(`virtual${flag}`); @@ -148,6 +163,47 @@ "folder with changed flag and descendants should be added to the virtual folder" ); + // Test what happens if a folder of one type is not added to a parent in the + // virtual folder of another type. This should really only matter for inboxes + // containing other types of folders, which happens in some configurations. + // Other combinations shouldn't really exist, but let's test them anyway. + + if (!["SentMail", "Archive"].includes(flag)) { + for (let otherFlag of [ + "Inbox", + "Drafts", + "Templates", + "SentMail", + "Archive", + "Junk", + "Trash", + ]) { + if (otherFlag == flag) { + continue; + } + let otherFlagChild = MailServices.folderLookup.getOrCreateFolderForURL( + `${rootFolder.URI}/parent${flag}/other${otherFlag}Child` + ); + otherFlagChild.setFlag(Ci.nsMsgFolderFlags[otherFlag]); + parent.addSubfolder(otherFlagChild.name); + parent.notifyFolderAdded(otherFlagChild); + + if (flag == "Trash") { + checkVirtualFolder( + [more, evenMore, yetMore, parent, child, grandchild, otherFlagChild], + `folder with ${otherFlag} flag should be added to the virtual ${flag} folder` + ); + } else { + checkVirtualFolder( + [more, evenMore, yetMore, parent, child, grandchild], + `folder with ${otherFlag} flag should not be added to the virtual ${flag} folder` + ); + } + + parent.propagateDelete(otherFlagChild, false); + } + } + // Now reverse the additions. rootFolder.propagateDelete(parent, false); diff -Nru thunderbird-115.3.0+build2/comm/mailnews/compose/src/nsMsgCompose.cpp thunderbird-115.3.1+build1/comm/mailnews/compose/src/nsMsgCompose.cpp --- thunderbird-115.3.0+build2/comm/mailnews/compose/src/nsMsgCompose.cpp 2023-09-26 18:56:00.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/mailnews/compose/src/nsMsgCompose.cpp 2023-09-29 10:32:58.000000000 +0000 @@ -1595,9 +1595,22 @@ reference.Append(messageId); reference.Append('>'); m_compFields->SetReferences(reference.get()); + + if (type == nsIMsgCompType::ForwardInline) { + nsString subject; + msgHdr->GetMime2DecodedSubject(subject); + nsCString fwdPrefix; + prefs->GetCharPrefWithDefault("mail.forward_subject_prefix", "Fwd"_ns, + 1, fwdPrefix); + nsString unicodeFwdPrefix; + CopyUTF8toUTF16(fwdPrefix, unicodeFwdPrefix); + unicodeFwdPrefix.AppendLiteral(": "); + subject.Insert(unicodeFwdPrefix, 0); + m_compFields->SetSubject(subject); + } } - // Early return for "Forward inline" and "Reply with template" processing. + // Early return for "ForwardInline" and "ReplyWithTemplate" processing. return NS_OK; } @@ -1636,7 +1649,6 @@ NS_ENSURE_SUCCESS(rv, rv); } if (msgHdr) { - nsCString decodedCString; nsString subject; rv = msgHdr->GetMime2DecodedSubject(subject); if (NS_FAILED(rv)) return rv; @@ -1689,6 +1701,20 @@ switch (type) { default: break; + case nsIMsgCompType::Draft: + case nsIMsgCompType::Template: + case nsIMsgCompType::EditTemplate: + case nsIMsgCompType::EditAsNew: { + uint32_t flags; + msgHdr->GetFlags(&flags); + if (flags & nsMsgMessageFlags::HasRe) { + subject.InsertLiteral(u"Re: ", 0); + } + // Set subject from db, where it's already decrypted. The raw + // header may be encrypted. + m_compFields->SetSubject(subject); + break; + } case nsIMsgCompType::Reply: case nsIMsgCompType::ReplyAll: case nsIMsgCompType::ReplyToList: @@ -1729,7 +1755,6 @@ } uint32_t flags; - msgHdr->GetFlags(&flags); if (flags & nsMsgMessageFlags::HasRe) subject.InsertLiteral(u"Re: ", 0); @@ -1776,15 +1801,12 @@ if (isFirstPass) { nsCString fwdPrefix; - prefs->GetCharPref("mail.forward_subject_prefix", fwdPrefix); - if (!fwdPrefix.IsEmpty()) { - nsString unicodeFwdPrefix; - CopyUTF8toUTF16(fwdPrefix, unicodeFwdPrefix); - unicodeFwdPrefix.AppendLiteral(": "); - subject.Insert(unicodeFwdPrefix, 0); - } else { - subject.InsertLiteral(u"Fwd: ", 0); - } + prefs->GetCharPrefWithDefault("mail.forward_subject_prefix", + "Fwd"_ns, 1, fwdPrefix); + nsString unicodeFwdPrefix; + CopyUTF8toUTF16(fwdPrefix, unicodeFwdPrefix); + unicodeFwdPrefix.AppendLiteral(": "); + subject.Insert(unicodeFwdPrefix, 0); m_compFields->SetSubject(subject); } break; @@ -1794,6 +1816,7 @@ // original From: header... nsAutoCString author; msgHdr->GetAuthor(getter_Copies(author)); + m_compFields->SetSubject(subject); m_compFields->SetReplyTo(author.get()); // ... and empty out the various recipient headers diff -Nru thunderbird-115.3.0+build2/comm/SOURCE_CHANGESET thunderbird-115.3.1+build1/comm/SOURCE_CHANGESET --- thunderbird-115.3.0+build2/comm/SOURCE_CHANGESET 2023-09-26 18:56:02.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/SOURCE_CHANGESET 2023-09-29 10:33:00.000000000 +0000 @@ -1 +1 @@ -1218aebde8d83fe28bbdfe39c63d7a10044829c2 \ No newline at end of file +42b3addbca70f64493bdbede7f3f66dc40641a0a \ No newline at end of file diff -Nru thunderbird-115.3.0+build2/comm/taskcluster/comm_taskgraph/transforms/push_langpacks.py thunderbird-115.3.1+build1/comm/taskcluster/comm_taskgraph/transforms/push_langpacks.py --- thunderbird-115.3.0+build2/comm/taskcluster/comm_taskgraph/transforms/push_langpacks.py 2023-09-26 18:56:01.000000000 +0000 +++ thunderbird-115.3.1+build1/comm/taskcluster/comm_taskgraph/transforms/push_langpacks.py 2023-09-29 10:32:59.000000000 +0000 @@ -79,6 +79,7 @@ job, "worker.channel", item_name=job["label"], + project=config.params["project"], platform=job["primary-dependency"].attributes["build_platform"], ) diff -Nru thunderbird-115.3.0+build2/config/milestone.txt thunderbird-115.3.1+build1/config/milestone.txt --- thunderbird-115.3.0+build2/config/milestone.txt 2023-09-26 18:55:41.000000000 +0000 +++ thunderbird-115.3.1+build1/config/milestone.txt 2023-09-29 10:32:44.000000000 +0000 @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -115.3.0 +115.3.1 diff -Nru thunderbird-115.3.0+build2/debian/changelog thunderbird-115.3.1+build1/debian/changelog --- thunderbird-115.3.0+build2/debian/changelog 2023-09-28 11:09:35.000000000 +0000 +++ thunderbird-115.3.1+build1/debian/changelog 2023-09-29 11:58:23.000000000 +0000 @@ -1,3 +1,9 @@ +thunderbird (1:115.3.1+build1-0ubuntu0.23.04.1) lunar; urgency=medium + + * New upstream stable release (115.3.1+build1) + + -- Sebastien Bacher Fri, 29 Sep 2023 13:58:23 +0200 + thunderbird (1:115.3.0+build2-0ubuntu0.23.04.1) lunar; urgency=medium * New upstream stable release (115.3.0+build2) diff -Nru thunderbird-115.3.0+build2/media/libvpx/libvpx/test/encode_api_test.cc thunderbird-115.3.1+build1/media/libvpx/libvpx/test/encode_api_test.cc --- thunderbird-115.3.0+build2/media/libvpx/libvpx/test/encode_api_test.cc 2023-09-26 18:55:10.000000000 +0000 +++ thunderbird-115.3.1+build1/media/libvpx/libvpx/test/encode_api_test.cc 2023-09-29 10:32:11.000000000 +0000 @@ -307,7 +307,6 @@ void InitCodec(const vpx_codec_iface_t &iface, int width, int height, vpx_codec_ctx_t *enc, vpx_codec_enc_cfg_t *cfg) { - ASSERT_EQ(vpx_codec_enc_config_default(&iface, cfg, 0), VPX_CODEC_OK); cfg->g_w = width; cfg->g_h = height; cfg->g_lag_in_frames = 0; @@ -345,6 +344,7 @@ vpx_codec_ctx_t ctx = {}; } enc; + ASSERT_EQ(vpx_codec_enc_config_default(iface, &cfg, 0), VPX_CODEC_OK); EXPECT_NO_FATAL_FAILURE( InitCodec(*iface, kWidth, kHeight, &enc.ctx, &cfg)); if (IsVP9(iface)) { @@ -356,6 +356,50 @@ for (const auto threads : { 1, 4, 8, 6, 2, 1 }) { cfg.g_threads = threads; + EXPECT_NO_FATAL_FAILURE(EncodeWithConfig(cfg, &enc.ctx)) + << "iteration: " << i << " threads: " << threads; + } + } + } +} + +TEST(EncodeAPI, ConfigResizeChangeThreadCount) { + constexpr int kInitWidth = 1024; + constexpr int kInitHeight = 1024; + + for (const auto *iface : kCodecIfaces) { + SCOPED_TRACE(vpx_codec_iface_name(iface)); + for (int i = 0; i < (IsVP9(iface) ? 2 : 1); ++i) { + vpx_codec_enc_cfg_t cfg = {}; + struct Encoder { + ~Encoder() { EXPECT_EQ(vpx_codec_destroy(&ctx), VPX_CODEC_OK); } + vpx_codec_ctx_t ctx = {}; + } enc; + + ASSERT_EQ(vpx_codec_enc_config_default(iface, &cfg, 0), VPX_CODEC_OK); + // Start in threaded mode to ensure resolution and thread related + // allocations are updated correctly across changes in resolution and + // thread counts. See https://crbug.com/1486441. + cfg.g_threads = 4; + EXPECT_NO_FATAL_FAILURE( + InitCodec(*iface, kInitWidth, kInitHeight, &enc.ctx, &cfg)); + if (IsVP9(iface)) { + EXPECT_EQ(vpx_codec_control_(&enc.ctx, VP9E_SET_TILE_COLUMNS, 6), + VPX_CODEC_OK); + EXPECT_EQ(vpx_codec_control_(&enc.ctx, VP9E_SET_ROW_MT, i), + VPX_CODEC_OK); + } + + cfg.g_w = 1000; + cfg.g_h = 608; + EXPECT_EQ(vpx_codec_enc_config_set(&enc.ctx, &cfg), VPX_CODEC_OK) + << vpx_codec_error_detail(&enc.ctx); + + cfg.g_w = 16; + cfg.g_h = 720; + + for (const auto threads : { 1, 4, 8, 6, 2, 1 }) { + cfg.g_threads = threads; EXPECT_NO_FATAL_FAILURE(EncodeWithConfig(cfg, &enc.ctx)) << "iteration: " << i << " threads: " << threads; } diff -Nru thunderbird-115.3.0+build2/media/libvpx/libvpx/vp8/encoder/onyx_if.c thunderbird-115.3.1+build1/media/libvpx/libvpx/vp8/encoder/onyx_if.c --- thunderbird-115.3.0+build2/media/libvpx/libvpx/vp8/encoder/onyx_if.c 2023-09-26 18:55:10.000000000 +0000 +++ thunderbird-115.3.1+build1/media/libvpx/libvpx/vp8/encoder/onyx_if.c 2023-09-29 10:32:10.000000000 +0000 @@ -1447,6 +1447,12 @@ last_h = cpi->oxcf.Height; prev_number_of_layers = cpi->oxcf.number_of_layers; + if (cpi->initial_width) { + // TODO(https://crbug.com/1486441): Allow changing thread counts; the + // allocation is done once in vp8_create_compressor(). + oxcf->multi_threaded = cpi->oxcf.multi_threaded; + } + cpi->oxcf = *oxcf; switch (cpi->oxcf.Mode) { diff -Nru thunderbird-115.3.0+build2/SOURCE_CHANGESET thunderbird-115.3.1+build1/SOURCE_CHANGESET --- thunderbird-115.3.0+build2/SOURCE_CHANGESET 2023-09-26 18:56:02.000000000 +0000 +++ thunderbird-115.3.1+build1/SOURCE_CHANGESET 2023-09-29 10:33:00.000000000 +0000 @@ -1 +1 @@ -17bedcda2f5c28b7fbc136d300bdbbf04f382e00 \ No newline at end of file +749617c4473c65f8aebb2e3254777ae99dc17cce \ No newline at end of file