diff --git a/third_party/firefox_sendtophone/chrome/content/ff-overlay.js b/third_party/firefox_sendtophone/chrome/content/ff-overlay.js index 32b12b6..eab4333 100644 --- a/third_party/firefox_sendtophone/chrome/content/ff-overlay.js +++ b/third_party/firefox_sendtophone/chrome/content/ff-overlay.js @@ -108,51 +108,67 @@ sendtophone.checkDrag = function(event) sendtophone.doDrop = function(event) { - var types = event.dataTransfer.types; - var supportedTypes = ["application/x-moz-file", "text/uri-list", "text/x-moz-url", "text/plain"]; + var dt = event.dataTransfer + var types = dt.types; + var supportedTypes = ["application/x-moz-file", "text/x-moz-url", "text/uri-list", "text/plain"]; types = supportedTypes.filter(function (value) types.contains(value)); - if (types.length) - var plainText = event.dataTransfer.getData(types[0]); - var mozUrlArray = event.dataTransfer.getData(types[1]).split("\n"); - var mozUrl = mozUrlArray[0]; - var mozTitle = mozUrlArray[1]; + event.preventDefault(); switch (types[0]) { case "text/plain": + var plainText = dt.getData(types[0]); sendtophoneCore.send("Selection", "http://google.com", plainText); break; - case "text/uri-list": + case "text/x-moz-url": + var mozUrlArray = dt.getData(types[1]).split("\n"); + var mozUrl = mozUrlArray[0]; + var mozTitle = mozUrlArray[1] || ''; sendtophoneCore.send(mozTitle, mozUrl, ""); break; - case "application/x-moz-file": - var file = event.dataTransfer.mozGetDataAt("application/x-moz-file", 0); - if (file instanceof Components.interfaces.nsIFile && file.isFile() ) - { - var url = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService) - .getProtocolHandler("file") - .QueryInterface(Ci.nsIFileProtocolHandler) - .getURLSpecFromFile(file); + case "text/uri-list": + var mozUrl = dt.getData(types[0]); + sendtophoneCore.send("", mozUrl, ""); + break; - sendtophoneCore.send("", url, ""); + case "application/x-moz-file": + for (var i = 0; i < dt.mozItemCount; i++) + { + var file = dt.mozGetDataAt("application/x-moz-file", i); + if (file instanceof Components.interfaces.nsIFile ) + { + sendtophoneCore.sendFile(file); + } + else + this.alert(this.strings.getString("InvalidFile")); } - else - this.alert(this.strings.getString("InvalidFile")); + break; } } -sendtophone.sendFile = function() +sendtophone.pickFile = function(folder) { var fp = Cc["@mozilla.org/filepicker;1"] .createInstance(Ci.nsIFilePicker); - fp.init(window, this.strings.getString("SendFileToPhone"), Ci.nsIFilePicker.modeOpen); + if (folder) + fp.init(window, this.strings.getString("SendFolderToPhone"), Ci.nsIFilePicker.modeGetFolder); + else + fp.init(window, this.strings.getString("SendFileToPhone"), Ci.nsIFilePicker.modeOpenMultiple); fp.appendFilters(Ci.nsIFilePicker.filterAll | Ci.nsIFilePicker.filterImages); var rv = fp.show(); + if (rv == Ci.nsIFilePicker.returnOK) - sendtophoneCore.send('', fp.fileURL.spec, ''); + { + var files = fp.files; + while (files.hasMoreElements()) + { + var file = files.getNext().QueryInterface(Ci.nsILocalFile); + sendtophoneCore.sendFile( file ); + } + } + } diff --git a/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul b/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul index 3c3e8f2..3260fc5 100644 --- a/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul +++ b/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul @@ -13,7 +13,10 @@ + oncommand="sendtophone.pickFile(false)" id="sendtophoneContextMenuSendFile"/> + diff --git a/third_party/firefox_sendtophone/chrome/locale/en/overlay.dtd b/third_party/firefox_sendtophone/chrome/locale/en/overlay.dtd index 0ccc2fd..c533b8f 100644 --- a/third_party/firefox_sendtophone/chrome/locale/en/overlay.dtd +++ b/third_party/firefox_sendtophone/chrome/locale/en/overlay.dtd @@ -12,5 +12,7 @@ - + + + diff --git a/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties b/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties index 7ef92ce..ede4699 100644 --- a/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties +++ b/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties @@ -14,4 +14,5 @@ mmsLink=MMS Number mmstoLink=MMS Number telLink=Telephone Number InvalidFile=Not a valid file -SendFileToPhone=Send a file to your phone \ No newline at end of file +SendFileToPhone=Send files to your phone. +SendFolderToPhone=Send a folder to your phone. diff --git a/third_party/firefox_sendtophone/chrome/locale/es/overlay.dtd b/third_party/firefox_sendtophone/chrome/locale/es/overlay.dtd index 1b24c43..8d0c1db 100644 --- a/third_party/firefox_sendtophone/chrome/locale/es/overlay.dtd +++ b/third_party/firefox_sendtophone/chrome/locale/es/overlay.dtd @@ -12,5 +12,7 @@ - + + + diff --git a/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties b/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties index d5bbfcc..d5d432b 100644 --- a/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties +++ b/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties @@ -14,4 +14,5 @@ mmsLink=Número MMS mmstoLink=Número MMS telLink=Número de teléfono InvalidFile=Solo se puede enviar un fichero cada vez. -SendFileToPhone=Envía un fichero al teléfono. \ No newline at end of file +SendFileToPhone=Envía ficheros al teléfono. +SendFolderToPhone=Envía una carpeta al teléfono. diff --git a/third_party/firefox_sendtophone/modules/sendtophone.js b/third_party/firefox_sendtophone/modules/sendtophone.js index 748ecce..087aaf9 100644 --- a/third_party/firefox_sendtophone/modules/sendtophone.js +++ b/third_party/firefox_sendtophone/modules/sendtophone.js @@ -87,12 +87,9 @@ var sendtophoneCore = { processXHR: function(url, method, data, callback) { - if (!this.req) - this.req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] + var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Ci.nsIXMLHttpRequest); - var req = this.req; - req.open(method, url, true); req.setRequestHeader('X-Same-Domain', 'true'); // XSRF protector @@ -155,7 +152,12 @@ var sendtophoneCore = { // Local files: upload them to a web server if ((/^file:/i).test(url)) { - this.sendFile(url); + var nsFile = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService) + .getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler) + .getFileFromURLSpec(url); + this.sendFile(nsFile); return; } @@ -281,16 +283,28 @@ var sendtophoneCore = { return data + converter.Finish(); }, - sendFile: function(fileURL) + sendFile: function( nsFile, callback ) { - var nsFile = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService) - .getProtocolHandler("file") - .QueryInterface(Ci.nsIFileProtocolHandler) - .getFileFromURLSpec(fileURL); + if (!this.prefs) + this.init(); - if (!nsFile.isFile()) + if (nsFile.isDirectory()) + { + // Compress the contents to a zip file + zipFolder(nsFile, function(nsZip) + { + // Send the zip and delete it afterwards + sendtophoneCore.sendFile(nsZip, function() {/* nsZip.remove(false)*/ }); + } + ) return; + } + + if (!nsFile.isFile()) + { + this.alert(this.getString("InvalidFile")); + return; + } var uploadName = nsFile.leafName; // Try to determine the MIME type of the file @@ -350,12 +364,16 @@ var sendtophoneCore = { if (body && (uploads = body.documentElement.getElementsByTagName("upload"))) { sendtophoneCore.send(uploadName, uploads[0].firstChild.data, ""); - return + // If there's a callback (to delete temporary files) we call it now + if (callback) + callback(); + return; } // error. - sendtophoneCore.alert(event.target.responseText); + sendtophoneCore.alert(uri + "\r\n" + event.target.responseText); } /* + if required for cookies... don't think so. try { req.channel.QueryInterface(Ci.nsIHttpChannelInternal). forceAllowThirdPartyCookie = true; @@ -367,3 +385,69 @@ var sendtophoneCore = { }; + +/* Zipping functions */ +const PR_RDONLY = 0x01; +const PR_WRONLY = 0x02; +const PR_RDWR = 0x04; +const PR_CREATE_FILE = 0x08; +const PR_APPEND = 0x10; +const PR_TRUNCATE = 0x20; +const PR_SYNC = 0x40; +const PR_EXCL = 0x80; + +/** +* folder is a nsFile pointing to a folder +* callback is a function that it's called after the zip is created. It has one parameter: the nsFile created +*/ +function zipFolder(folder, callback) +{ + // get TMP directory + var nsFile = Components.classes["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties). + get("TmpD", Ci.nsIFile); + + // Create a new file + nsFile.append( folder.leafName + ".zip"); + nsFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); + + var zipWriter = Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter"); + var zipW = new zipWriter(); + + zipW.open(nsFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE); + + addFolderContentsToZip(zipW, folder, ""); + + // We don't want to block the main thread, so the zipping is done asynchronously + // and here we get the notification that it has finished + var observer = { + onStartRequest: function(request, context) {}, + onStopRequest: function(request, context, status) + { + zipW.close(); + // Notify that we're done. Now it must be sent and deleted afterwards + callback(nsFile); + } + } + + zipW.processQueue(observer, null); +} + +/** +* function to add the contents of a folder recursively +* zipW a nsIZipWriter object +* folder a nsFile object pointing to a folder +* root a string defining the relative path for this folder in the zip +*/ +function addFolderContentsToZip(zipW, folder, root) +{ + var entries = folder.directoryEntries; + while(entries.hasMoreElements()) + { + var entry = entries.getNext(); + entry.QueryInterface(Ci.nsIFile); + zipW.addEntryFile(root + entry.leafName, Ci.nsIZipWriter.COMPRESSION_DEFAULT, entry, true); + if (entry.isDirectory()) + addFolderContentsToZip(zipW, entry, root + entry.leafName + "/"); + } +} \ No newline at end of file