diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..76acca5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +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 Source Code Form is “Incompatible With Secondary Licenses”, +as defined by the Mozilla Public License, v. 2.0. diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..1838548 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +##### Makefile for generating the add-on as a XPI archive +# +# v1 2011-10-20 MKA +# v2 2011-10-25 MKA Added checks + +DEBUG_STR = ">>> Did you reset the debug level in chrome/content/tnef.js?" +MANIF_STR = ">>> Did you change back the jar directive in chrome.manifest?" + +ZIP_CMD = zip -r # archive recursively (the defaults directory) + # -f could be used to update only if the xpi archive exists permanently +XPI_FILE = lookout.xpi +LIC_FILE = LICENSE +CHRO_DIR = chrome +DEFA_DIR = defaults +MAN_FILE = chrome.manifest +INS_FILE = install.rdf +JAR_FILE = $(CHRO_DIR)/lookout.jar + +all: check jar xpi + +check: # Make checks first + echo $(DEBUG_STR) && read ANSWER + echo $(MANIF_STR) && read ANSWER + +jar: # Generating the JAR archive + cd $(CHRO_DIR) && make jar + +xpi: $(JAR_FILE) $(MAN_FILE) $(INS_FILE) # Generating the XPI archive + $(ZIP_CMD) $(XPI_FILE) $(JAR_FILE) $(DEFA_DIR)/* $(MAN_FILE) $(INS_FILE) $(LIC_FILE) + +clean: + rm -f $(XPI_FILE) $(JAR_FILE) + diff --git a/README.md b/README.md new file mode 100755 index 0000000..f4ff328 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +LookOut for Seamonkey +===================== + +Since Seamonkey 2.0 the Add-on LookOut doesn't work. The main aim of this project is to fix this problem, since the TNEF coded attachments can't be opened and saved. + +This repo is forked from the [LookOut Thunderbird Add-on](https://github.com/AronRubin/LookOut) of Aron Rubin. diff --git a/Version.inf b/Version.inf new file mode 100755 index 0000000..96524a4 --- /dev/null +++ b/Version.inf @@ -0,0 +1,7 @@ +Version 1.2.15 +2013-10-11 Taking over corrections for saving the attachment by Paul Richardson +2013-10-11 Adding icons +2013-10-12 Removed obsolete code +2013-10-14 Code changes according to Mozilla validation results [setTimeout(), Array.prototype] +2013-10-15 Code changes according to Mozilla validation results [nsILocalFile, gHeaderParser] + diff --git a/chrome.manifest b/chrome.manifest old mode 100644 new mode 100755 index ce7251d..17ffd1e --- a/chrome.manifest +++ b/chrome.manifest @@ -1,4 +1,12 @@ -content lookout jar:chrome/lookout.jar!/content/ -locale lookout en-US jar:chrome/lookout.jar!/locale/en-US/ -skin lookout classic/1.0 jar:chrome/lookout.jar!/skin/ -overlay chrome://messenger/content/mailWindowOverlay.xul chrome://lookout/content/lookout.xul +content lookout chrome/content/ +locale lookout hu chrome/locale/hu/ +locale lookout de chrome/locale/de/ +locale lookout en-US chrome/locale/en-US/ +skin lookout classic/1.0 chrome/skin/ + +# content lookout jar:chrome/lookout.jar!/content/ +# locale lookout en-US jar:chrome/lookout.jar!/locale/en-US/ +# locale lookout hu jar:chrome/lookout.jar!/locale/hu/ +# locale lookout de jar:chrome/lookout.jar!/locale/de/ +# skin lookout classic/1.0 jar:chrome/lookout.jar!/skin/ +overlay chrome://messenger/content/mailWindowOverlay.xul chrome://lookout/content/lookout.xul diff --git a/chrome.manifest.final b/chrome.manifest.final new file mode 100755 index 0000000..805c47e --- /dev/null +++ b/chrome.manifest.final @@ -0,0 +1,7 @@ +content lookout jar:chrome/lookout.jar!/content/ +locale lookout en-US jar:chrome/lookout.jar!/locale/en-US/ +locale lookout hu jar:chrome/lookout.jar!/locale/hu/ +locale lookout de jar:chrome/lookout.jar!/locale/de/ +skin lookout classic/1.0 jar:chrome/lookout.jar!/skin/ +overlay chrome://messenger/content/mailWindowOverlay.xul chrome://lookout/content/lookout.xul + diff --git a/chrome/Makefile b/chrome/Makefile old mode 100644 new mode 100755 index 3843508..7713665 --- a/chrome/Makefile +++ b/chrome/Makefile @@ -1,4 +1,28 @@ -all:lookout.jar +# all:lookout.jar +# +# lookout.jar: content/*.js content/*.xul locale/en-US/*.dtd locale/en-US/*.properties skin/*.css +# zip -f $@ $^ + +##### Makefile for generating the JAR archive +# +# v1 2011-10-20 MKA + +JAR_CMD = jar cvfM +JAR_BASE = . +JAR_FILE = lookout.jar +CONT_DIR = content +LOCA_DIR = locale +SKIN_DIR = skin +JS_FILES := $(wildcard $(JAR_BASE)/$(CONT_DIR)/*.js) +XUL_FILES := $(wildcard $(JAR_BASE)/$(CONT_DIR)/*.xul) +LOC_FILES := $(wildcard $(JAR_BASE)/$(LOCA_DIR)/*) +CSS_FILES := $(wildcard $(JAR_BASE)/$(SKIN_DIR)/*.css) +ICO_FILES := $(wildcard $(JAR_BASE)/$(SKIN_DIR)/LOicon*.png) + +all: jar + +# Generating the JAR archive +jar: $(JS_FILES) $(XUL_FILES) $(LOC_FILES) $(CSS_FILES) $(ICO_FILES) + $(JAR_CMD) $(JAR_FILE) $(JS_FILES) $(XUL_FILES) $(LOC_FILES) $(CSS_FILES) $(ICO_FILES) + -lookout.jar: content/*.js content/*.xul locale/en-US/*.dtd locale/en-US/*.properties skin/*.css - zip -f $@ $^ diff --git a/chrome/content/Makefile b/chrome/content/Makefile deleted file mode 100644 index fee8cea..0000000 --- a/chrome/content/Makefile +++ /dev/null @@ -1,3 +0,0 @@ - -all: - cd .. && make diff --git a/chrome/content/lookout.js b/chrome/content/lookout.js old mode 100644 new mode 100755 index 4b8097a..ad5eba8 --- a/chrome/content/lookout.js +++ b/chrome/content/lookout.js @@ -87,6 +87,11 @@ var lookout = { }, basename: function lo_basename( path ) { + //MKA Mozilla suggests to replace nsILocalFile with nsIFile *if older versions* + // *are not supported*. But we still want to! + // 'Local' was merged back into its parent class in Gecko 14 (Thunderbird 14 / + // SeaMonkey 2.11), but it is not intended to remove the 'Loclal' interface. + // https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Versions/14#Interfaces var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); try { @@ -279,6 +284,7 @@ LookoutStreamListener.prototype = { }, onStopRequest: function ( aRequest, aContext, aStatusCode ) { + lookout.log_msg( "LookOut: Entering onStopRequest()", 6 ); //MKA var channel = aRequest.QueryInterface(Components.interfaces.nsIChannel); var fsm; @@ -289,7 +295,7 @@ LookoutStreamListener.prototype = { } if( !(this.mMsgUri == fsm && this.mStream) ) { - lookout.log_msg( "LookOut: strange things a foot", 5 ); + lookout.log_msg( "LookOut: strange things a foot", 5 ); aRequest.cancel( Components.results.NS_BINDING_ABORTED ); return; } @@ -301,6 +307,7 @@ LookoutStreamListener.prototype = { }, onDataAvailable: function ( aRequest, aContext, aInputStream, aOffset, aCount ) { + lookout.log_msg( "LookOut: Entering onDataAvailable()", 6 ); //MKA var fsm; try { @@ -310,7 +317,7 @@ LookoutStreamListener.prototype = { } if( this.mMsgUri != fsm ) { - lookout.log_msg( "LookOut: data available wrong", 5 ); + lookout.log_msg( "LookOut: data available wrong", 15 ); //MKA 5 aRequest.cancel( Components.results.NS_BINDING_ABORTED ); return; } @@ -319,10 +326,12 @@ LookoutStreamListener.prototype = { this.stream_started = true; } - this.mPackage = tnef_pack_parse_stream( this.mStream, this.mMsgHdr, this, this.mPackage ); + this.mPackage = tnef_pack_parse_stream( this.mStream, this.mMsgHdr, this, + this.mPackage ); }, onTnefStart: function ( filename, content_type, length, date ) { + lookout.log_msg( "LookOut: Entering onTnefStart()", 6 ); //MKA var mimeurl = this.mAttUrl + "." + this.mPartId; var basename = lookout.basename( filename ); @@ -334,11 +343,11 @@ LookoutStreamListener.prototype = { if( this.action_type == LOOKOUT_ACTION_SCAN ) { - lookout.log_msg( "adding attachment: " + mimeurl, 7 ); + lookout.log_msg( "LookOut: adding attachment: " + mimeurl, 7 ); lookout_lib.add_sub_attachment_to_list( this.attachment, content_type, filename, this.mPartId, mimeurl, this.mMsgUri, length ); } else { - lookout.log_msg( "open or save: " + this.mAttUrl + "." + this.mPartId, 7 ); + lookout.log_msg( "LookOut: open or save: " + this.mAttUrl + "." + this.mPartId, 7 ); if( !this.req_part_id || this.mPartId == this.req_part_id ) { // ensure these are null for the following case evaluation this.cur_outstrm = null; @@ -374,64 +383,89 @@ LookoutStreamListener.prototype = { } } } - lookout.log_msg( "LookOut: onTnefStart\nParent: " + this.attachment + - "\nmMsgUri: "+this.mMsgUri + - "\nrequested Part_ID: " + this.req_part_id + - "\nPart_ID: " + this.mPartId + - "\nDisplayname: " + filename.split("\0")[0] + - "\nContent-Type: " + content_type.split("\0")[0] + - "\nLength: " + length + - "\nURL: " + (this.cur_url ? this.cur_url.spec : "") + - "\nmimeurl: " + (mimeurl ? mimeurl : ""), 7 ); + lookout.log_msg( "LookOut: Parent: " + this.attachment + + "\n mMsgUri: " + this.mMsgUri + + "\n requested Part_ID: " + this.req_part_id + + "\n Part_ID: " + this.mPartId + + "\n Displayname: " + filename.split("\0")[0] + + "\n Content-Type: " + content_type.split("\0")[0] + + "\n Length: " + length + + "\n URL: " + (this.cur_url ? this.cur_url.spec : "") + + "\n mimeurl: " + (mimeurl ? mimeurl : ""), 7 ); }, onTnefEnd: function ( ) { - lookout.log_msg( "LookOut: onTnefEnd", 8 ); + lookout.log_msg( "LookOut: Entering onTnefEnd()", 6 ); if( this.cur_outstrm ) this.cur_outstrm.close(); if( !this.req_part_id || this.mPartId == this.req_part_id ) { switch( this.action_type ) { + case LOOKOUT_ACTION_SAVE: - lookout.log_msg( "Saving attachment '" + this.cur_url.spec + "'", 7 ); - messenger.saveAttachment( this.cur_content_type, this.cur_url.spec, this.cur_filename, this.mMsgUri, true ); - break; + lookout.log_msg( "LookOut: saving attachment '" + this.cur_url.path + "'", 7 ); + // messenger.saveAttachment( this.cur_content_type, this.cur_url.spec, + // this.cur_filename, this.mMsgUri, true ); + try { + var file = this.cur_url.QueryInterface(Components.interfaces.nsIFileURL).file; + } catch (ex) { + alert("LookOut: error creating file : " + this.cur_url.path + " : " + ex); + } + var nsIFilePicker = Components.interfaces.nsIFilePicker; + var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); + fp.init(window, "Select a File", nsIFilePicker.modeSave); + fp.appendFilters(nsIFilePicker.filterAll); + fp.defaultString = this.cur_filename; + var res = fp.show(); + if (res != nsIFilePicker.returnCancel){ + try { + file.moveTo(fp.displayDirectory, fp.file.leafName); + } catch(ex) { + alert( "LookOut: error moving file : " + fp.displayDirectory.path + + " : " + fp.file.leafName + " : " + ex); + } + } + break; + case LOOKOUT_ACTION_OPEN: - lookout.log_msg( "Opening attachment '"+ this.cur_url.spec+"'", 7 ); - if( lookout.get_bool_pref( "direct_to_calendar" ) && - this.cur_content_type == "text/calendar" && this.cur_outstrm_listener ) { - var cal_items = new Array(); + lookout.log_msg( "LookOut: opening attachment '"+ this.cur_url.spec+"'", 7 ); + if (lookout.get_bool_pref( "direct_to_calendar" ) + && this.cur_content_type == "text/calendar" + && this.cur_outstrm_listener) { + var cal_items = new Array(); + + try { + var instrm = this.cur_outstrm.QueryInterface(Components.interfaces.nsIStorageStream).newInputStream( 0 ); + cal_items = this.cur_outstrm_listener.importFromStream( instrm, { } ); + instrm.close(); + } catch (ex) { + lookout.log_msg( "LookOut: error opening calendar stream: " + ex, 3 ); + } + var count_o = new Object(); + var cal_mgr = Components.classes["@mozilla.org/calendar/manager;1"].getService(Components.interfaces.calICalendarManager); + var calendars = cal_mgr.getCalendars( count_o ); - try { - var instrm = this.cur_outstrm.QueryInterface(Components.interfaces.nsIStorageStream).newInputStream( 0 ); - cal_items = this.cur_outstrm_listener.importFromStream( instrm, { } ); - instrm.close(); - } catch (ex) { - lookout.log_msg( "LookOut: error opening calendar stream: " + ex, 3 ); - } - var count_o = new Object(); - var cal_mgr = Components.classes["@mozilla.org/calendar/manager;1"].getService(Components.interfaces.calICalendarManager); - var calendars = cal_mgr.getCalendars( count_o ); - - if (count_o.value == 1) { + if (count_o.value == 1) { // There's only one calendar, so it's silly to ask what calendar // the user wants to import into. - lookout.cal_add_items( calendars[0], cal_items, this.cur_filename ); - } else { - var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService); - var cal_strbundle = sbs.createBundle("chrome://calendar/locale/calendar.properties"); + lookout.cal_add_items( calendars[0], cal_items, this.cur_filename ); + } else { + var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService); + var cal_strbundle = sbs.createBundle("chrome://calendar/locale/calendar.properties"); - // Ask what calendar to import into - var args = new Object(); - args.onOk = function putItems(aCal) { lookout.cal_add_items( aCal, cal_items, this.cur_filename ); }; - args.promptText = cal_strbundle.GetStringFromName( "importPrompt" ); - openDialog( "chrome://calendar/content/chooseCalendarDialog.xul", - "_blank", "chrome,titlebar,modal,resizable", args ); - } - } else { - messenger.openAttachment( this.cur_content_type, this.cur_url.spec, this.cur_filename, this.mMsgUri, true ); - } - break; + // Ask what calendar to import into + var args = new Object(); + args.onOk = function putItems(aCal) { lookout.cal_add_items( aCal, cal_items, this.cur_filename ); }; + args.promptText = cal_strbundle.GetStringFromName( "importPrompt" ); + openDialog( "chrome://calendar/content/chooseCalendarDialog.xul", + "_blank", "chrome,titlebar,modal,resizable", args ); + } + } else { + messenger.openAttachment( this.cur_content_type, this.cur_url.spec, + this.cur_filename, this.mMsgUri, true ); + } + break; + } } @@ -448,10 +482,11 @@ LookoutStreamListener.prototype = { }, onTnefData: function ( position, data ) { - lookout.log_msg( "LookOut: onTnefData position " + position + " data.len " + data.length + " outstrm " + this.cur_outstrm, 7 ); + lookout.log_msg( "LookOut: onTnefData position " + position + " data.len " + + data.length + " outstrm " + this.cur_outstrm, 7 ); if( this.cur_outstrm ) { if( data ) { - lookout.log_msg( "LookOut: writing " + data.length + "bytes to file", 7 ); + lookout.log_msg( "LookOut: writing " + data.length + "bytes to file", 7 ); this.cur_outstrm.write( data, data.length ); } } @@ -474,56 +509,35 @@ var DecapsulateMsgHeaderSink = { */ var lookout_lib = { - orig_openAttachment: null, - orig_saveAttachment: null, orig_onEndAllAttachments: null, orig_processHeaders: null, - orig_cloneAttachment: null, - init_wait: 0, - onload: function() { + startup: function() { + lookout.log_msg( "LookOut: Entering startup()", 6 ); //MKA + // FIXME - Register onEndAllAttachments listener with messageHeaderSink - // For now monkey patch messageHeaderSink.onEndAllAttachments and messageHeaderSink.processHeaders + // For now monkey patch messageHeaderSink.onEndAllAttachments (and messageHeaderSink.processHeaders?) // (see mail/base/content/msgHdrOverlay.js). - // Make sure other global init has finished e.g. messageHeaderSink - // has been defined if( typeof messageHeaderSink != 'undefined' && messageHeaderSink ) { lookout_lib.orig_onEndAllAttachments = messageHeaderSink.onEndAllAttachments; messageHeaderSink.onEndAllAttachments = lookout_lib.on_end_all_attachments; + lookout.log_msg( "LookOut: registering messageHeaderSink.onEndAllAttachments hook", 6 ); //MKA } else { - if ( lookout_lib.init_wait < LOOKOUT_WAIT_MAX ) { - lookout_lib.init_wait++; - lookout.log_msg( "LookOut: waiting for global init (" + lookout_lib.init_wait + ")"); - setTimeout( lookout_lib.onload, LOOKOUT_WAIT_TIME ); - return; - - } else { - lookout.log_msg( "LookOut: Warning initialisation incomplete", 2 ); - } + lookout.log_msg( "LookOut: failed to register messageHeaderSink.onEndAllAttachments hook", 2 ); //MKA } - lookout.log_msg( "LookOut: Waited " + lookout_lib.init_wait + " times for global init" ); - lookout_lib.init_wait = 0; - + var listener = {}; listener.onStartHeaders = lookout_lib.on_start_headers; listener.onEndHeaders = lookout_lib.on_end_headers; gMessageListeners.push( listener ); - // FIXME - fix mozilla so there is a cleaner way here - // monkey patch the openAttachment and saveAttachment functions - if( typeof openAttachment != 'undefined' && openAttachment ) { - lookout_lib.orig_openAttachment = openAttachment; - openAttachment = lookout_lib.open_attachment; - } - if( typeof saveAttachment != 'undefined' && saveAttachment ) { - lookout_lib.orig_saveAttachment = saveAttachment; - saveAttachment = lookout_lib.save_attachment; - } - if( typeof cloneAttachment != 'undefined' && cloneAttachment ) { - lookout_lib.orig_cloneAttachment = cloneAttachment; - cloneAttachment = lookout_lib.clone_attachment; - } + //AR: Monkey patch the openAttachment and saveAttachment functions + //MKA: It was a general solution for every attachments. + // Fixed in version 1.2.12: the hook is added only to TNEF attachments + // in function add_sub_attachment_to_list() + // openAttachment() and saveAttachment() functions are globally no longer available + // after Thunderbird 7. So this part was obsolate. }, msg_hdr_for_current_msg: function( msg_uri ) { @@ -546,7 +560,7 @@ var lookout_lib = { } if( !hdr && gDBView.msgFolder ) { try { - hdr = gDBView.msgFolder.GetMessageHeader( gDBView.getKeyAt( gDBView.currentlyDisplayedMessage ) ); + hdr = gDBView.msgFolder.GetMessageHeader( gDBView.getKeyAt( gDBView.currentlyDisplayedMessage ) ); } catch( ex ) { } } if( !hdr && messageHeaderSink ) @@ -556,6 +570,7 @@ var lookout_lib = { }, scan_for_tnef: function ( ) { + lookout.log_msg( "LookOut: Entering scan_for_tnef()", 6); var messenger2 = Components.classes["@mozilla.org/messenger;1"] .getService(Components.interfaces.nsIMessenger); @@ -565,7 +580,7 @@ var lookout_lib = { lookout.log_msg( attachment.toSource(), 8 ); // we only decode tnef files if( (/^application\/ms-tnef/i).test( attachment.contentType ) ) { - lookout.log_msg( "LookOut: found tnef", 7 ); + lookout.log_msg( "LookOut: found tnef", 7 ); // open the attachment and look inside var stream_listener = new LookoutStreamListener(); @@ -577,7 +592,7 @@ var lookout_lib = { stream_listener.mMsgUri = attachment.messageUri; stream_listener.mMsgHdr = lookout_lib.msg_hdr_for_current_msg( stream_listener.mMsgUri ); if( ! stream_listener.mMsgHdr ) - lookout.log_msg( "LookOut: no message header for this service", 5 ); + lookout.log_msg( "LookOut: no message header for this service", 5 ); stream_listener.action_type = LOOKOUT_ACTION_SCAN; var mms = messenger2.messageServiceFromURI( stream_listener.mMsgUri ) @@ -591,37 +606,60 @@ var lookout_lib = { }, add_sub_attachment_to_list: function ( parent, content_type, display_name, part_id, atturl, msguri, length ) { + lookout.log_msg( "LookOut: Entering add_sub_attachment_to_list()", 6); var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch); - /* - var attachmentList = document.getElementById( 'attachmentList' ); - var i = 0; - - for( i = 0; i < attachmentList.childNodes.length && - attachmentList.childNodes[i].attachment.url != attUrl; i++ ); + lookout.log_msg( "LookOut: content_type:" + content_type + + "\n atturl:" + atturl + + "\n display_name:" + display_name + + "\n msguri:" + msguri, 8 ); - // if we found our list item then we are done - if( i >= attachmentList.childNodes.length ) - return; - */ - lookout.log_msg( " content_type:"+content_type +", atturl:"+ atturl +", display_name:"+ display_name +", msguri:"+ msguri, 8 ); var attachment = null; - if( typeof AttachmentInfo != 'undefined' ) - var attachment = new AttachmentInfo( content_type, atturl, display_name, msguri, true, length ) - else - var attachment = new createNewAttachmentInfo( content_type, atturl, display_name, msguri, true ) + if( typeof AttachmentInfo != 'undefined' ) { + // New naming -- used since Thunderbird 7.* + // http://mxr.mozilla.org/comm-central/source/mail/base/content/msgHdrViewOverlay.js#1642 + var attachment = new AttachmentInfo( content_type, atturl, display_name, msguri, true, length ); + lookout.log_msg( "LookOut: found new type object: AttachmentInfo ~ Thunderbird 7", 6 ); //MKA + } + else { + // Old naming -- used in Seamonkey 2.* (until Thunderbird 3.*) + // http://mxr.mozilla.org/comm-central/source/suite/mailnews/msgHdrViewOverlay.js#1201 + var attachment = new createNewAttachmentInfo( content_type, atturl, display_name, msguri, true ); + lookout.log_msg( "LookOut: found old type object: createNewAttachmentInfo ~ Seamonkey", 6 ); //MKA + } + if( attachment.open ) { + // New naming -- used since Thunderbird 7.* attachment.lo_orig_open = attachment.open; attachment.open = function () { lookout_lib.open_attachment( this ); }; + lookout.log_msg( "LookOut: registered own function for attachment.open", 6 ); //MKA + } else { + // Old naming -- used in Seamonkey 2.* (until Thunderbird 3.*) + attachment.lo_orig_open = attachment.openAttachment; + attachment.openAttachment = function () { + lookout_lib.open_attachment( this ); + }; + lookout.log_msg( "LookOut: registered own function for attachment.openAttachment", 6 ); } + if( attachment.save ) { + // New naming -- used since Thunderbird 7.* attachment.lo_orig_save = attachment.save; attachment.save = function () { lookout_lib.save_attachment( this ); }; + lookout.log_msg( "LookOut: registered own function for attachment.save", 6 ); //MKA + } else { + // Old naming -- used in Seamonkey 2.* (until Thunderbird 3.*) + attachment.lo_orig_save = attachment.saveAttachment; + attachment.saveAttachment = function () { + lookout_lib.save_attachment( this ); + }; + lookout.log_msg( "LookOut: registered own function for attachment.saveAttachment", 6 ); } + attachment.parent = parent; attachment.part_id = part_id; currentAttachments.push( attachment ); @@ -634,7 +672,7 @@ var lookout_lib = { // e.g. messageHeaderSink.OnEndAllAttachments // (see mail/base/content/msgHdrViewOverlay.js) redraw_attachment_view: function ( atturl ) { - lookout.log_msg( "Lookout: redraw_attachment_view()", 8 ); + lookout.log_msg( "Lookout: Entering redraw_attachment_view()", 6 ); ClearAttachmentList(); gBuildAttachmentsForCurrentMsg = false; // TODO - make sure attachment popup menu is not broken @@ -644,20 +682,22 @@ var lookout_lib = { // try to call "Attachment Sizes", extension {90ceaf60-169c-40fb-b224-7204488f061d} if( typeof ABglobals != 'undefined' ) { try { - ABglobals.setAttSizeTextFor( atturl, length, false ); + ABglobals.setAttSizeTextFor( atturl, length, false ); } catch(ex) {} } }, open_attachment: function ( attachment ) { - lookout.log_msg( attachment.toSource(), 8 ); + lookout.log_msg( "LookOut: Entering open_attachment()", 6 ); //MKA + lookout.log_msg( "LookOut: got attachment = " + attachment.toSource(), 10 ); + // There is no TNEF attachment, use the original OPEN function + //MKA: Though no longer necessary, since we register the own open_attachment() + // function for TNEF attachments only (after version 1.2.12) if( !attachment.parent || !(/^application\/ms-tnef/i).test( attachment.parent.contentType ) ) { - if( attachment.lo_orig_open ) - attachment.lo_orig_open(); - else if( lookout_lib.orig_openAttachment ) - lookout_lib.orig_openAttachment( attachment ); + if( attachment.lo_orig_open ) // this is the original open() function + attachment.lo_orig_open(); return; } @@ -675,34 +715,43 @@ var lookout_lib = { var attname = attachment.name ? attachment.name : attachment.displayName; - lookout.log_msg( "open_attachment\nParent: "+(attachment.parent == null ? "-" : attachment.parent.url) - +"\nContent-Type: "+attachment.contentType.split("\0")[0] - +"\nDisplayname: "+attname.split("\0")[0] - +"\nPart_ID: "+attachment.part_id - +"\nisExternal: "+attachment.isExternalAttachment - +"\nURL: "+attachment.url - +"\nmMsgUri: "+stream_listener.mMsgUri, 7 ); + lookout.log_msg( "LookOut: Parent: " + (attachment.parent == null ? "-" : attachment.parent.url) + + "\n Content-Type: " + attachment.contentType.split("\0")[0] + + "\n Displayname: " + attname.split("\0")[0] + + "\n Part_ID: " + attachment.part_id + + "\n isExternal: " + attachment.isExternalAttachment + + "\n URL: " + attachment.url + + "\n mMsgUri: " + stream_listener.mMsgUri, 7 ); var mms = messenger2.messageServiceFromURI( stream_listener.mMsgUri ) - .QueryInterface( Components.interfaces.nsIMsgMessageService ); - + .QueryInterface( Components.interfaces.nsIMsgMessageService ); attname = attachment.parent.name ? attachment.parent.name : attachment.parent.displayName; - mms.openAttachment( attachment.parent.contentType, attname, - attachment.parent.url, stream_listener.mMsgUri, stream_listener, - null, null ); + // http://mxr.mozilla.org/comm-central/source/mailnews/base/public/nsIMsgMessageService.idl#131 + mms.openAttachment( attachment.parent.contentType // in string aContentType + , attname // in string aFileName + , attachment.parent.url // in string aUrl + , stream_listener.mMsgUri // in string aMessageUri + , stream_listener // in nsISupports aDisplayConsumer + , null // in nsIMsgWindow aMsgWindow + , null ); // in nsIUrlListener aUrlListener }, save_attachment: function ( attachment ) { + lookout.log_msg( "LookOut: Entering save_attachment()", 6 ); //MKA + lookout.log_msg( "LookOut: got attachment = " + attachment.toSource(), 10 ); + + // There is no TNEF attachment, use the original SAVE function + //MKA: Though no longer necessary, since we register the own save_attachment() + // function for TNEF attachments only (after version 1.2.12) if( !attachment.parent || !(/^application\/ms-tnef/i).test( attachment.parent.contentType ) ) { - if( attachment.lo_orig_save ) - attachment.lo_orig_save(); - else if( lookout_lib.orig_saveAttachment ) - lookout_lib.orig_saveAttachment( attachment ); + if( attachment.lo_orig_save ) // this is the original save() function + attachment.lo_orig_save(); return; } var messenger2 = Components.classes["@mozilla.org/messenger;1"] .getService(Components.interfaces.nsIMessenger); + var stream_listener = new LookoutStreamListener(); stream_listener.req_part_id = attachment.part_id; stream_listener.mAttUrl = attachment.parent.url; @@ -715,35 +764,28 @@ var lookout_lib = { var attname = attachment.name ? attachment.name : attachment.displayName; - lookout.log_msg( "save_attachment\nParent: "+(attachment.parent == null ? "-" : attachment.parent.url) - +"\nContent-Type: "+attachment.contentType.split("\0")[0] - +"\nDisplayname: "+attname.split("\0")[0] - +"\nPart_ID: "+attachment.part_id - +"\nisExternal: "+attachment.isExternalAttachment - +"\nURL: "+attachment.url - +"\nmMsgUri: "+stream_listener.mMsgUri, 7 ); + lookout.log_msg( "LookOut: Parent: " + (attachment.parent == null ? "-" : attachment.parent.url) + + "\n Content-Type: " + attachment.contentType.split("\0")[0] + + "\n Displayname: " + attname.split("\0")[0] + + "\n Part_ID: " + attachment.part_id + + "\n isExternal: " + attachment.isExternalAttachment + + "\n URL: " + attachment.url + + "\n mMsgUri: " + stream_listener.mMsgUri, 7 ); var mms = messenger2.messageServiceFromURI( stream_listener.mMsgUri ) .QueryInterface( Components.interfaces.nsIMsgMessageService ); attname = attachment.parent.name ? attachment.parent.name : attachment.parent.displayName; + +//MKA The comment is misleading, because it has nothing to do with the Save File Dialogue here. +// See onTnefEnd() in LookoutStreamListener.prototype! + // Using the same function as for OPEN and hoping that the user has not set default action + // for this file type... mms.openAttachment( attachment.parent.contentType, attname, attachment.parent.url, stream_listener.mMsgUri, stream_listener, null, null ); }, - clone_attachment: function( attachment ) { - if( !attachment.parent || - !(/^application\/ms-tnef/i).test( attachment.parent.contentType ) ) { - return lookout_lib.orig_cloneAttachment( attachment ); - } - - //TODO original code didn't clone. is it necessary? - var obj = lookout_lib.orig_cloneAttachment( attachment ); - obj.parent = attachment.parent; - obj.part_id = attachment.part_id; - return obj; - }, - on_end_all_attachments: function () { + lookout.log_msg( "LookOut: Entering on_end_all_attachments()", 6 ); //MKA //attachment parsing has finished lookout_lib.scan_for_tnef(); //call hijacked onEndAllAttachments @@ -763,5 +805,32 @@ var lookout_lib = { //setTimeout( lookout_lib.scan_for_tnef, 100 ); } } -window.addEventListener( 'load', lookout_lib.onload, false ); + +var LookoutInitWait = 0; + +function LookoutLoad () { + lookout.log_msg( "LookOut: Entering LookoutLoad()", 6 ); //MKA + // Make sure other global init has finished + // e.g. messageHeaderSink has been defined + if( typeof messageHeaderSink == 'undefined' ) { + if ( LookoutInitWait < LOOKOUT_WAIT_MAX ) { + LookoutInitWaitt++; + lookout.log_msg( "LookOut: waiting for global init [" + LookoutInitWait + "]", 6 ); + //MKA Function referencing in setTimeout() is deprecated by Mozilla, + // so the following function expression is used. + // https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval + setTimeout( function() { LookoutLoad() }, LOOKOUT_WAIT_TIME ); + return; + } else { + lookout.log_msg( "LookOut: initialisation incomplete after " + + LookoutInitWait + " trials. I give up!", 2 ); + return; + } + } + LookoutInitWait = 0; + lookout_lib.startup(); +} + +//MKA Adding callback to the mail window for starting addon. +window.addEventListener( 'load', LookoutLoad, false ); diff --git a/chrome/content/tnef.js b/chrome/content/tnef.js old mode 100644 new mode 100755 index a30b69f..2b557d0 --- a/chrome/content/tnef.js +++ b/chrome/content/tnef.js @@ -11,7 +11,7 @@ * Calendaring and contact data is transcoded to standards formats. */ -const debugLevel = 5; +const debugLevel = 7; //MKA Set 5 to switch off; const LVL_MESSAGE = 0x1; @@ -387,13 +387,18 @@ function concat_fname( fname1, fname2 ) { } function fs_file_exists( fname ) { + //MKA Mozilla suggests to replace nsILocalFile with nsIFile *if older versions* + // *are not supported*. But we still want to! + // 'Local' was merged back into its parent class in Gecko 14 (Thunderbird 14 / + // SeaMonkey 2.11), but it is not intended to remove the 'Loclal' interface. + // https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Versions/14#Interfaces var lf = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); lf.initWithPath( fname ); return( lf.exists() ); } // finds a filename fname.N where N >= 1 and is not the name of an existing -// filename. Assumes that fname does not already have such an extension +// filename. Assumes that fname does not already have such an extension function fs_find_free_number( fname ) { var newname = ""; var counter = 1; @@ -516,7 +521,8 @@ function tnef_file_write_stream( file, outstrm ) { function tnef_file_notify( file, listener, is_final ) { - tnef_log_msg( "LookOut: notifying listener of " + file.name + ", pos = " + file.position + + tnef_log_msg( "TNEF: Entering tnef_file_notify()", 6); //MKA + tnef_log_msg( "TNEF: Notifying listener of " + file.name + ", pos = " + file.position + ", has data = " + (file.data ? "true" : "false") + ", is final = " + is_final, 7 ); @@ -800,13 +806,14 @@ function tnef_attr_read( instrm, prev_attr ) { tnef_byte_pos += 9; } - tnef_log_msg( "reading attr" + - " lvl_type 0x" + to_hex( attr.lvl_type, 1 ) + - " name " + tnef_attr_name_to_string( attr.name ) + - " type " + tnef_attr_type_to_string( attr.type ) + - " length " + attr.len + - " togo " + (attr.len - (attr.buf ? attr.buf.length : 0)) + - " pos in TNEF " + tnef_byte_pos - 9, 6 ); + tnef_log_msg( "TNEF: reading attr\n" + + " lvl_type: 0x" + to_hex( attr.lvl_type, 1 ) + + ", name: " + tnef_attr_name_to_string( attr.name ) + + ", type: " + tnef_attr_type_to_string( attr.type ) + + ", length: " + attr.len + + ", togo: " + (attr.len - (attr.buf ? attr.buf.length : 0)) // attr.buf might be NULL! + + ", pos in TNEF: " + (tnef_byte_pos - 9) + , 15 ); //MKA 6 var available = instrm.available(); if( available > 0 ) { @@ -833,7 +840,7 @@ function tnef_attr_read( instrm, prev_attr ) { //tnef_attr_dbg_dump( attr ); } } else { - tnef_log_msg( "waiting for " + (attr.len - attr.buf.length) + " more bytes", 8 ); + tnef_log_msg( "TNEF: waiting for " + (attr.len - attr.buf.length) + " more bytes", 20 ); //MKA 8 } } @@ -1249,6 +1256,10 @@ function strtrim( str ) { return( match && match.length > 0 ? match[0] : '' ); } +//MKA gHeaderParser was removed in Thunderbird 13, but nsIMsgHeaderParser is still +// available! +// https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIMsgHeaderParser + // This is needed because nsIMsgHeaderParser cannot handle the commas MS allows // in the phrase and hangs if the email is invalid function decompose_rfc822_address( address ) { @@ -1267,10 +1278,14 @@ function decompose_rfc822_address( address ) { } -// forEach used below so ensure recomended implementation exists +/* +// .forEach used below to ensure that recomended implementation exists +//MKA Extension of a built-in JS type is not allowed by Mozilla. +// This code is no longer needed anyhow. if (!Array.prototype.forEach) { - Array.prototype.forEach = function(fun /*, thisp*/) + tnef_log_msg( "TNEF: Extending built-in Array type with .forEach()", 6 ); //MKA + Array.prototype.forEach = function(fun) //(fun, thisp) { var len = this.length; if (typeof fun != "function") @@ -1283,9 +1298,12 @@ if (!Array.prototype.forEach) fun.call(thisp, this[i], i, this); } }; +} else { + tnef_log_msg( "TNEF: Built-in Array type has .forEach()", 6 ); //MKA } +*/ -var gHeaderParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser); +var ownHeaderParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser); function tnef_pack_get_name_addr( pkg, orig_name_addr ) { var orig_addr_parts = decompose_rfc822_address( orig_name_addr ); @@ -1304,13 +1322,13 @@ function tnef_pack_get_name_addr( pkg, orig_name_addr ) { orig_addr_parts[1] = ""; - num_addrs = gHeaderParser.parseHeadersWithArray( pkg.msg_header.author, addrs, names, full_names ); + num_addrs = ownHeaderParser.parseHeadersWithArray( pkg.msg_header.author, addrs, names, full_names ); all_addrs = addrs.value; all_names = names.value; - num_addrs += gHeaderParser.parseHeadersWithArray( pkg.msg_header.recipients, addrs, names, full_names ); + num_addrs += ownHeaderParser.parseHeadersWithArray( pkg.msg_header.recipients, addrs, names, full_names ); all_addrs = all_addrs.concat( addrs.value ); all_names = all_names.concat( names.value ); - num_addrs += gHeaderParser.parseHeadersWithArray( pkg.msg_header.ccList, addrs, names, full_names ); + num_addrs += ownHeaderParser.parseHeadersWithArray( pkg.msg_header.ccList, addrs, names, full_names ); all_addrs = all_addrs.concat( addrs.value ); all_names = all_names.concat( names.value ); @@ -1787,6 +1805,8 @@ function tnef_pack_parse_stream( instrm, msg_header, listener, prev_pack ) { var sig = 0; var key = 0; var pkg = null; + + tnef_log_msg( "TNEF: Entering tnef_pack_parse_stream()", 6); //MKA if( prev_pack ) { pkg = prev_pack; @@ -1815,7 +1835,7 @@ function tnef_pack_parse_stream( instrm, msg_header, listener, prev_pack ) { while( pkg.cur_attr && tnef_pack_data_left( instrm ) ) { if( pkg.cur_attr.name == TNEF_ATTR_OEM_CODEPAGE ) { pkg.code_page = GETINT32( pkg.cur_attr.buf ); - tnef_log_msg( "Lookout: OEM Code Page = " + pkg.code_page, 7 ); + tnef_log_msg( "TNEF: OEM Code Page = " + pkg.code_page, 7 ); } // This signals the beginning of a file if( pkg.cur_attr.name == TNEF_ATTR_ATTACH_REND_DATA ) { diff --git a/chrome/locale/de/lookout.dtd b/chrome/locale/de/lookout.dtd new file mode 100755 index 0000000..506cbb5 --- /dev/null +++ b/chrome/locale/de/lookout.dtd @@ -0,0 +1 @@ + diff --git a/chrome/locale/de/lookout.properties b/chrome/locale/de/lookout.properties new file mode 100755 index 0000000..5bda868 --- /dev/null +++ b/chrome/locale/de/lookout.properties @@ -0,0 +1,6 @@ +extensions.lookout.body_part_prefix=Hauptteil_ +extensions.lookout.description=LookOut öffnet die TNEF kodierten Anhaenge der Mails und ladet sie herunter +extensions.lookout.attach_raw_mapi=false +extensions.lookout.direct_to_calendar=false +extensions.lookout.disable_filename_character_set=false + diff --git a/chrome/locale/de/prefwindow.dtd b/chrome/locale/de/prefwindow.dtd new file mode 100755 index 0000000..d398c4b --- /dev/null +++ b/chrome/locale/de/prefwindow.dtd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/chrome/locale/hu/lookout.dtd b/chrome/locale/hu/lookout.dtd new file mode 100755 index 0000000..506cbb5 --- /dev/null +++ b/chrome/locale/hu/lookout.dtd @@ -0,0 +1 @@ + diff --git a/chrome/locale/hu/lookout.properties b/chrome/locale/hu/lookout.properties new file mode 100755 index 0000000..5fb4438 --- /dev/null +++ b/chrome/locale/hu/lookout.properties @@ -0,0 +1,6 @@ +extensions.lookout.body_part_prefix=törzs_ +extensions.lookout.description=A MutasdMeg! (LookOut) megnyitja és letölthetõvé teszi a levelek TNEF kódolással csatolt mellékleteit +extensions.lookout.attach_raw_mapi=false +extensions.lookout.direct_to_calendar=false +extensions.lookout.disable_filename_character_set=false + diff --git a/chrome/locale/hu/prefwindow.dtd b/chrome/locale/hu/prefwindow.dtd new file mode 100755 index 0000000..c26159c --- /dev/null +++ b/chrome/locale/hu/prefwindow.dtd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/chrome/skin/LOicon-32.png b/chrome/skin/LOicon-32.png new file mode 100755 index 0000000..b219f21 Binary files /dev/null and b/chrome/skin/LOicon-32.png differ diff --git a/chrome/skin/LOicon-64.png b/chrome/skin/LOicon-64.png new file mode 100755 index 0000000..eb011b3 Binary files /dev/null and b/chrome/skin/LOicon-64.png differ diff --git a/defaults/preferences/lookout.js b/defaults/preferences/lookout.js old mode 100644 new mode 100755 diff --git a/install.rdf b/install.rdf old mode 100644 new mode 100755 index d1e847e..a491832 --- a/install.rdf +++ b/install.rdf @@ -1,20 +1,43 @@ - - lookout@aron.rubin - LookOut - 1.2.13 + + lookout@addons.mozilla.org + 1.2.15 + 2 + + + hu + MutasdMeg! (LookOut) + A LookOut megnyitja és letölthetővé teszi a levelek TNEF kódolással csatolt mellékleteit (általában winmail.dat). + Rubin, Aron + Mergl K. Attila + + + + + de + Zeig'sMir! (LookOut) + LookOut öffnet die TNEF kodierten Anhänge der Mails (meistens winmail.dat) und ladet die dekodierten Teile herunter. + Aron Rubin + Attila K. Mergl + + + LookOut+ + LookOut reads and integrates TNEF encoded parts in emails. Aron Rubin - LookOut reads and integrates TNEF encoded parts in emails - http://lookout.mozdev.org + Attila K. Mergl + Paul Richardson + https://addons.mozilla.org/hu/seamonkey/addon/lookout-1/ chrome://lookout/content/options.xul + chrome://lookout/skin/LOicon-32.png + chrome://lookout/skin/LOicon-64.png - + {3550f703-e582-4d05-9a08-453d09bdfdc6} 1.5 - 7.* + 24.* @@ -22,8 +45,8 @@ {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} - 1.1 - 2.3.* + 1.0 + 2.*