www.pudn.com > addons.rar > mocoJoey.js
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Joey Mozilla Project. * * The Initial Developer of the Original Code is * Doug Turner. * Portions created by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var moco_joey_url = "https://joey.labs.mozilla.com"; var g_joey_hasLogged = false; var g_joey_in_progress = false; function getJoeyURL() { var psvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); var url = moco_joey_url; if (psvc.prefHasUserValue("joey.service_url")) url = psvc.getCharPref("joey.service_url"); return url; } function debug(str) { var console = Components.classes["@mozilla.org/consoleservice;1"] .getService(Components.interfaces.nsIConsoleService); console.logStringMessage("Joey!: "+ str); } function JoeyStreamListener(self, aCallbackFunc, aListener) { this.mOwner = self; this.mCallbackFunc = aCallbackFunc; } JoeyStreamListener.prototype = { mBytes: [], mStream: null, mCount: 0, mOwner: null, // nsIStreamListener onStartRequest: function (aRequest, aContext) { this.mStream = Components.classes["@mozilla.org/scriptableinputstream;1"] .createInstance(Components.interfaces.nsIScriptableInputStream); }, onDataAvailable: function (aRequest, aContext, aStream, aSourceOffset, aCount) { this.mStream.init(aStream); this.mBytes += this.mStream.read(aCount); this.mCountRead += aCount; }, onStopRequest: function (aRequest, aContext, aStatus) { var joeyResponse = -1; try { var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel); joeyResponse = httpChannel.getResponseHeader("X-joey-status"); } catch (e) {} this.mCallbackFunc(this.mOwner, joeyResponse, this.mBytes); }, // nsIChannelEventSink onChannelRedirect: function (aOldChannel, aNewChannel, aFlags) { }, // nsIInterfaceRequestor getInterface: function (aIID) { try { return this.QueryInterface(aIID); } catch(ex) {} }, // nsIProgressEventSink onProgress : function (aRequest, aContext, aProgress, aProgressMax) { if (this.mOwner != null && this.mOwner.joey_listener != null) this.mOwner.joey_listener.onProgressChange(aProgress, aProgressMax); }, onStatus : function (aRequest, aContext, aStatus, aStatusArg) { }, // nsIHttpEventSink (not implementing will cause annoying exceptions) onRedirect : function (aOldChannel, aNewChannel) { }, QueryInterface : function(aIID) { if (aIID.equals(Components.interfaces.nsISupports) || aIID.equals(Components.interfaces.nsIInterfaceRequestor) || aIID.equals(Components.interfaces.nsIChannelEventSink) || aIID.equals(Components.interfaces.nsIProgressEventSink) || aIID.equals(Components.interfaces.nsIHttpEventSink) || aIID.equals(Components.interfaces.nsIStreamListener)) return this; throw Components.results.NS_NOINTERFACE; } }; function mocoJoey() { this._init(); } mocoJoey.prototype = { joey_listener: null, joey_username: "", joey_password: "", joey_data: "", joey_content_type: "", joey_title: "", joey_url: "", xmlhttp: null, setLoginInfo: function() { this.joey_username = ""; this.joey_password = ""; var passwordManager = Components.classes["@mozilla.org/passwordmanager;1"] .getService(Components.interfaces.nsIPasswordManager); var e = passwordManager.enumerator; while (e.hasMoreElements()) { try { var pass = e.getNext().QueryInterface(Components.interfaces.nsIPassword); if (pass.host == getJoeyURL()) { this.joey_username = pass.user; this.joey_password = pass.password; return true; } } catch (ex) {} } /* We get the strings from the locale properties file */ var stringBundle = Components.classes["@mozilla.org/intl/stringbundle;1"] .getService(Components.interfaces.nsIStringBundleService); var joeyStrings = stringBundle.createBundle("chrome://joey/locale/joey.properties"); var promptTitle = joeyStrings.GetStringFromName("promptUserPass.windowtitle"); var promptQuestion = joeyStrings.GetStringFromName("promptUserPass.question"); var promptButton = joeyStrings.GetStringFromName("promptUserPass.button"); /* All good, render the prompt with right strings.. */ var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService); var u = {value: ""}; // default the username to user var p = {value: ""}; // default the password to pass var check = {value: true}; // default the checkbox to true var result = prompts.promptUsernameAndPassword(null, promptTitle, promptQuestion, u, p, promptButton, check); if (!result) { // cancel was pressed. return false; } // result is true if OK was pressed, false if cancel was pressed. username.value, // password.value, and check.value are set if OK was pressed. if (check.value) passwordManager.addUser(getJoeyURL(), u.value, u.value); this.joey_username = u.value; this.joey_password = p.value; return true; }, uploadData: function(title, url, data, type) { this.joey_isfile = false; this.uploadDataInternal( title, url, data, type); }, uploadFile: function(title, url, file, type) { this.joey_isfile = true; this.uploadDataInternal( title, url, file, type); }, uploadDataInternal: function(title, url, data, type) { if (g_joey_in_progress == true) return -1; g_joey_in_progress = true; this.joey_title = title; this.joey_url = url; this.joey_content_type = type; this.joey_data = data; // kick off the action if (g_joey_hasLogged == false) { if (this.setLoginInfo() == false) { g_joey_in_progress = false; this.joey_title = null; this.joey_url = null; this.joey_content_type = null; this.joey_data = null; return -1; } this.loginToService(); } else this.uploadDataFromGlobals(); }, setListener: function(listener) { this.joey_listener = listener; }, _init: function() { const osvr = Components.classes['@mozilla.org/observer-service;1'] .getService(Components.interfaces.nsIObserverService); osvr.addObserver(this, "profile-change-teardown", false); }, // nsIObserver implementation observe: function(subject, topic, data) { switch(topic) { case "profile-change-teardown": { // get rid of all of the rss prefs. try { var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService) .getBranch("joey.rss"); prefs.deleteBranch(""); } catch (a) {alert(a);} } break; } }, QueryInterface: function (iid) { if (iid.equals(Components.interfaces.mocoJoey) || iid.equals(Components.interfaces.nsIObserver) || iid.equals(Components.interfaces.nsISupports)) return this; Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE; return null; }, loginCallback: function (self, status, bytes) { if (status == 200) { g_joey_hasLogged = true; if (self.joey_listener != null) self.joey_listener.onStatusChange("login", 0); // continue going. self.uploadDataFromGlobals(); return; } if (self.joey_listener != null) { self.joey_listener.onStatusChange("login", -1); } g_joey_hasLogged=false; g_joey_in_progress = false; self.setListener(null); }, loginToService: function() { // get an listener var listener = new JoeyStreamListener(this, this.loginCallback, null); // the IO service var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); // create an nsIURI var urlstring = getJoeyURL() + "/users/login"; var uri = ioService.newURI(urlstring, null, null); // get a channel for that nsIURI var channel = ioService.newChannelFromURI(uri); // Create an input stream with the right data. var postData = "rest=1&data[User][username]=" + this.joey_username + "&data[User][password]=" + this.joey_password; var inputStream = Components.classes["@mozilla.org/io/string-input-stream;1"] .createInstance(Components.interfaces.nsIStringInputStream); inputStream.setData(postData, postData.length); // set the input stream on the channel. var uploadChannel = channel.QueryInterface(Components.interfaces.nsIUploadChannel); uploadChannel.setUploadStream(inputStream, "application/x-www-form-urlencoded", -1); var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel); httpChannel.requestMethod = "POST"; // order important - setUploadStream resets to PUT //channel.notificationCallbacks = listener; channel.asyncOpen(listener, null); }, uploadCallback: function (self, status, bytes) { var listener = self.joey_listener; self.setListener(null); g_joey_in_progress = false; if (listener == null) return; if (status == 200 || status == 519) // if all okay, or if there is a dup. { listener.onStatusChange("upload", 1); // 1 = okay all good. return; } if (status == 517) // Out of Space for Upload { // Not enough space left for user listener.onStatusChange("upload", -2); return; } if (status == 511) { // set the hasLogged to false, and try again. g_joey_in_progress = false; g_joey_hasLogged = false; this.uploadDataInternal( this.joey_title, this.joey_url, this.joey_file, this.joey_content_type); return; } // TODO: if it is a No Active Session error, try // relogging in a # of times. // // TODO: map more of the http status codes to // something the client might want to deal with. // General error listener.onStatusChange("upload", -1); return; }, uploadDataFromGlobals: function () { const BOUNDARY="111222111"; var mis=Components.classes["@mozilla.org/io/multiplex-input-stream;1"] .createInstance(Components.interfaces.nsIMultiplexInputStream); var fileBuffer = null; if (this.joey_isfile == true) { var fin=Components.classes["@mozilla.org/network/file-input-stream;1"] .createInstance(Components.interfaces.nsIFileInputStream); fin.init(this.joey_data, 0x1, 0, 0); fileBuffer=Components.classes["@mozilla.org/network/buffered-input-stream;1"] .createInstance(Components.interfaces.nsIBufferedInputStream); fileBuffer.init(fin, 4096); } var preamble = Components.classes["@mozilla.org/io/string-input-stream;1"] .createInstance(Components.interfaces.nsIStringInputStream); function createParam( name , value ) { return "--"+BOUNDARY+"\r\n" + "Content-disposition: form-data;name=\"" + name + "\"\r\n\r\n" + value + "\r\n"; } var start = createParam("rest", "1") + createParam("data[Upload][title]", this.joey_title) + createParam("data[Upload][referrer]", this.joey_url); var endstring; if (fileBuffer == null) { start += createParam("data[Contentsourcetype][name]", this.joey_content_type) + createParam("data[Contentsource][source]", this.joey_data); endstring = "--"+BOUNDARY+"--\r\n"; } else { endstring = "\r\n--"+BOUNDARY+"--\r\n"; } preamble.setData(start, start.length); mis.appendStream(preamble); if (fileBuffer != null) { var filePreamble = Components.classes["@mozilla.org/io/string-input-stream;1"] .createInstance(Components.interfaces.nsIStringInputStream); var filePreambleString = "--"+BOUNDARY+"\r\n" + "Content-disposition: form-data;name=\"data[File][Upload]\";filename=\"data[File][Upload]\"\r\n" + "Content-Type: " + this.joey_content_type + "\r\n" + "Content-Length: " + this.joey_data.fileSize + "\r\n\r\n"; filePreamble.setData(filePreambleString, filePreambleString.length); mis.appendStream(filePreamble); mis.appendStream(fileBuffer); } var postamble = Components.classes["@mozilla.org/io/string-input-stream;1"] .createInstance(Components.interfaces.nsIStringInputStream); postamble.setData(endstring, endstring.length); mis.appendStream(postamble); // get an listener var listener = new JoeyStreamListener(this, this.uploadCallback, null); // the IO service var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); // create an nsIURI var urlstring = getJoeyURL() + "/uploads/add"; var uri = ioService.newURI(urlstring, null, null); // get a channel for that nsIURI var channel = ioService.newChannelFromURI(uri); // set the input stream on the channel. var uploadChannel = channel.QueryInterface(Components.interfaces.nsIUploadChannel); uploadChannel.setUploadStream(mis, "multipart/form-data, boundary="+BOUNDARY, mis.available()); var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel); httpChannel.requestMethod = "POST"; // order important - setUploadStream resets to PUT channel.notificationCallbacks = listener; channel.asyncOpen(listener, null); }, }; var myModule = { firstTime: true, registerSelf: function (compMgr, fileSpec, location, type) { if (this.firstTime) { this.firstTime = false; throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN; } compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); compMgr.registerFactoryLocation(this.myCID, "Joey Mozilla Component", this.myProgID, fileSpec, location, type); }, getClassObject: function (compMgr, cid, iid) { if (!cid.equals(this.myCID)) throw Components.results.NS_ERROR_NO_INTERFACE; if (!iid.equals(Components.interfaces.nsIFactory)) throw Components.results.NS_ERROR_NOT_IMPLEMENTED; return this.myFactory; }, myCID: Components.ID("{66b3290c-6c74-4f15-8132-d6cc74e5d37f}"), myProgID: "@mozilla.com/joey;1", myFactory: { createInstance: function (outer, iid) { if (outer != null) throw Components.results.NS_ERROR_NO_AGGREGATION; return (new mocoJoey()).QueryInterface(iid); } }, canUnload: function(compMgr) { return true; } }; function NSGetModule(compMgr, fileSpec) { return myModule; }