TB-throwback / LookOut-fix-version

Fork of LookOut (fix version)
51 stars 17 forks source link

Can't process winmail.dat file with ics #95

Closed nagorny closed 1 year ago

nagorny commented 1 year ago

Ubuntu 22.10 Thunderbird 102.9.0 (64-bit) LookOut (fix version) version number: 5.3

Expected Behavior

I expected to process received ics file from winmail.dat but I can't. Even when I'm trying to save ics file from attach it says: "LookOut: error creating file : undefined : TypeError: this.cur_url.QueryInterface is not a function" winmail.dat.zip

dugite-code commented 1 year ago

Ok I was able to trigger this error myself with a separate email. However it is inconsistent and I am unable to determine the root cause at the moment.

This may be caused by the fact this isn't a true MailExtension and is using the compatibility layer.

*edit: I disabled the Remove Winmail.dat option and have not been able to trigger the issue again. May not be related but will continue investigating.

jobisoft commented 1 year ago

Could someone provide an STR and a winmail.dat file?

dugite-code commented 1 year ago

I've been able to reproduce with the winmail.dat attached by the OP now, it appears to be caused by the Open Calendaring Data Directly Option.

@jobisoft Here is the winmail.dat on an email for testing: message.eml.txt

@nagorny Please disable the Open Calendaring Data Directly Option by going add-on preferences in the Add-ons Manager -> Extensions menu and selecting the wrench next to the LookOut add-on.

It's possibly unrelated, but for some reason the error console is writing the contents of a function

Error log ``` LookOut: got attachment = ({message:({}), contentType:"text/calendar", name:"body_part_1.ics", url:"imap://dugite%252Ecode@mail.example.tld:993/fetch%253EUID%253E.Drafts%253E290?part=1.2&filename=winmail.dat.2", uri:"imap-message://dugite.code@mail.example.tld/Drafts#290", isExternalAttachment:true, size:573, sizeResolved:true, partID:"2", async lo_orig_open() { if (!this.hasFile || this.message != gFolderDisplay.selectedMessage) { return; } let bundleMessenger = document.getElementById("bundle_messenger"); let empty = await this.isEmpty(); if (empty) { let prompt = bundleMessenger.getString( this.isExternalAttachment ? "externalAttachmentNotFound" : "emptyAttachment" ); msgWindow.promptDialog.alert(null, prompt); } else { // @see MsgComposeCommands.js which has simililar opening functionality let dotPos = this.name.lastIndexOf("."); let extension = dotPos >= 0 ? this.name.substring(dotPos + 1).toLowerCase() : ""; if (this.contentType == "application/pdf" || extension == "pdf") { let handlerInfo = gMIMEService.getFromTypeAndExtension( this.contentType, extension ); // Only open a new tab for pdfs if we are handling them internally. if ( !handlerInfo.alwaysAskBeforeHandling && handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally ) { // Add the content type to avoid a "how do you want to open this?" // dialog. The type may already be there, but that doesn't matter. let url = this.url; if (!url.includes("type=")) { url += url.includes("?") ? "&" : "?"; url += "type=application/pdf"; } let tabmail = document.getElementById("tabmail"); if (!tabmail) { // If no tabmail available in this window, try and find it in // another. let win = Services.wm.getMostRecentWindow("mail:3pane"); tabmail = win && win.document.getElementById("tabmail"); } if (tabmail) { tabmail.openTab("contentTab", { url, background: false, linkHandler: "single-page", }); tabmail.ownerGlobal.focus(); return; } // If no tabmail, open PDF same as other attachments. } } // Just use the old method for handling messages, it works. if (this.contentType == "message/rfc822") { messenger.openAttachment( this.contentType, this.url, encodeURIComponent(this.name), this.uri, this.isExternalAttachment ); return; } // Get the MIME info from the service. let mimeInfo; try { mimeInfo = gMIMEService.getFromTypeAndExtension( this.contentType, extension ); } catch (ex) { // If the call above fails, which can happen on Windows where there's // nothing registered for the file type, assume this generic type. mimeInfo = gMIMEService.getFromTypeAndExtension( "application/octet-stream", "" ); } // The default action is saveToDisk, which is not what we want. // If we don't have a stored handler, ask before handling. if (!gHandlerService.exists(mimeInfo)) { mimeInfo.alwaysAskBeforeHandling = true; mimeInfo.preferredAction = Ci.nsIHandlerInfo.alwaysAsk; } // If we know what to do, do it. let { name, url } = this; name = DownloadPaths.sanitize(name); async function saveToFile(path) { let buffer = await new Promise(function(resolve, reject) { NetUtil.asyncFetch( { uri: Services.io.newURI(url), loadUsingSystemPrincipal: true, }, function(inputStream, status) { if (Components.isSuccessCode(status)) { resolve(NetUtil.readInputStream(inputStream)); } else { reject( new Components.Exception("Failed to fetch attachment", status) ); } } ); }); await IOUtils.write(path, new Uint8Array(buffer)); } let createTemporaryFileAndOpen = async mimeInfo => { let tmpPath = PathUtils.join( Services.dirsvc.get("TmpD", Ci.nsIFile).path, "pid-" + Services.appinfo.processID ); await IOUtils.makeDirectory(tmpPath, { permissions: 0o700 }); let tempFile = Cc["@mozilla.org/file/local;1"].createInstance( Ci.nsIFile ); tempFile.initWithPath(tmpPath); tempFile.append(name); tempFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); tempFile.remove(false); Cc["@mozilla.org/uriloader/external-helper-app-service;1"] .getService(Ci.nsPIExternalAppLauncher) .deleteTemporaryFileOnExit(tempFile); await saveToFile(tempFile.path); // Before opening from the temp dir, make the file read only so that // users don't edit and lose their edits... tempFile.permissions = 0o400; this._openFile(mimeInfo, tempFile); }; let openLocalFile = mimeInfo => { let fileHandler = Services.io .getProtocolHandler("file") .QueryInterface(Ci.nsIFileProtocolHandler); try { let externalFile = fileHandler.getFileFromURLSpec(this.displayUrl); this._openFile(mimeInfo, externalFile); } catch (ex) { Cu.reportError( "AttachmentInfo.open: file - " + this.displayUrl + ", " + ex ); } }; if (!mimeInfo.alwaysAskBeforeHandling) { switch (mimeInfo.preferredAction) { case Ci.nsIHandlerInfo.saveToDisk: if (Services.prefs.getBoolPref("browser.download.useDownloadDir")) { let destFile = new FileUtils.File( await Downloads.getPreferredDownloadsDirectory() ); destFile.append(name); destFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o755); destFile.remove(false); await saveToFile(destFile.path); } else { let filePicker = Cc["@mozilla.org/filepicker;1"].createInstance( Ci.nsIFilePicker ); filePicker.defaultString = this.name; filePicker.defaultExtension = extension; filePicker.init( window, bundleMessenger.getString("SaveAttachment"), Ci.nsIFilePicker.modeSave ); let rv = await new Promise(resolve => filePicker.open(resolve)); if (rv != Ci.nsIFilePicker.returnCancel) { await saveToFile(filePicker.file.path); } } return; case Ci.nsIHandlerInfo.useHelperApp: case Ci.nsIHandlerInfo.useSystemDefault: // Attachments can be detached and, if this is the case, opened from // their location on disk instead of copied to a temporary file. if (this.isExternalAttachment) { openLocalFile(mimeInfo); return; } await createTemporaryFileAndOpen(mimeInfo); return; } } // Ask what to do, then do it. let appLauncherDialog = Cc[ "@mozilla.org/helperapplauncherdialog;1" ].createInstance(Ci.nsIHelperAppLauncherDialog); appLauncherDialog.show( { QueryInterface: ChromeUtils.generateQI(["nsIHelperAppLauncher"]), MIMEInfo: mimeInfo, source: Services.io.newURI(this.url), suggestedFileName: this.name, cancel(reason) {}, promptForSaveDestination() { appLauncherDialog.promptForSaveToFileAsync( this, window, this.suggestedFileName, "." + extension, // Dot stripped by promptForSaveToFileAsync. false ); }, launchLocalFile() { openLocalFile(mimeInfo); }, async setDownloadToLaunch(handleInternally, file) { await createTemporaryFileAndOpen(mimeInfo); }, async saveDestinationAvailable(file) { if (file) { await saveToFile(file.path); } }, setWebProgressListener(webProgressListener) {}, targetFile: null, targetFileIsExecutable: null, timeDownloadStarted: null, contentLength: this.size, browsingContextId: getMessagePaneBrowser().browsingContext.id, }, window, null ); } }, open:(function () { lookout_lib.open_attachment( this ); }), async lo_orig_save() { if (!this.hasFile || this.message != gFolderDisplay.selectedMessage) { return; } let empty = await this.isEmpty(); if (empty) { return; } messenger.saveAttachment( this.contentType, this.url, encodeURIComponent(this.name), this.uri, this.isExternalAttachment ); }, save:(async function (save_dir) { return lookout_lib.save_attachment( this, save_dir ); }), parent:{message:({}), contentType:"", name:"winmail.dat", url:"imap://dugite%2Ecode@mail.example.tld:993/fetch%3EUID%3E.Drafts%3E290?part=1.2&filename=winmail.dat", uri:"imap-message://dugite.code@mail.example.tld/Drafts#290", isExternalAttachment:false, size:67292, sizeResolved:true, partID:"1.2"}}) ```
dugite-code commented 1 year ago

Closed due to webextension work. New implimentation to be discussed in #104