/*jslint rhino: true, forin: true, onevar: false, browser: true, evil: true, laxbreak: true, undef: true, nomen: true, eqeqeq: false, bitwise: true, maxerr: 1000, immed: false, white: false, plusplus: false, regexp: false, undef: false */
// Released under the MIT/X11 license
// http://www.opensource.org/licenses/mit-license.php
//
"use strict";
var preferences = require("preferences-service");
var prompts = require("prompts");
var clipboard = require("clipboard");
var tabs = require("tabs");
var logger = require("logger");
var passUtils = require("passwords");
var Request = require("request").Request;
var selfMod = require("self");
var urlMod = require("url");
var JSONURLDefault = "https://fedorahosted.org/released"+
"/bugzilla-triage-scripts/Config_data.json";
var BTSPrefNS = "bugzilla-triage.setting.";
var BTSPassRealm = "BTSXMLRPCPass";
function Message(cmd, data) {
console.log("Message: cmd = " + cmd + ", data = " + data);
this.cmd = cmd;
this.data = data;
}
function log(msg) {
postMessage(new Message("LogMessage", msg));
}
/**
* parse XML object out of string working around various bugs in Gecko implementation
* see https://developer.mozilla.org/en/E4X for more information
*
* @param inStr String with unparsed XML string
* @return XML object
*/
function parseXMLfromString (inStuff) {
// if (typeof inStuff !== 'string') In future we should recognize this.response
// and get just .text property out of it. TODO
var respStr = inStuff.replace(/^<\?xml\s+version\s*=\s*(["'])[^\1]+\1[^?]*\?>/, ""); // bug 336551
return new XML(respStr);
}
/**
* In case URL contains alias, not the real bug number, get the real bug no
* from the XML representation. Sets correct value to this.bugNo.
*
* somewhere in RPC functions which need it, we should have
* if (isNAN(parseInt(bugNo, 10))) {
* getRealBugNo(bugNo, location, callback);
* }
* Or not
*/
function getRealBugNo(bugNo, location, callback) {
console.log("We have to deal with bug aliased as " + this.bugNo);
// https://bugzilla.redhat.com/show_bug.cgi?ctype=xml&id=serialWacom
Request({
url: location.href+"&ctype=xml",
onComplete: function(response) {
if (response.status === 200) {
var xmlRepr = parseXMLfromString(response.text);
// TODO this is probably wrong, both XPath and .text attribute
var bugID = parseInt(xmlRepr.bug.bug_id.text, 10);
if (isNaN(bugID)) {
throw new Error("Cannot get bug no. even from XML representation!");
}
console.log("The real bug no. is " + bugID);
callback(bugID)
}
}
}).get();
}
exports.getPassword = function getPassword(login, domain, callback) {
var passPrompt = "Enter your Bugzilla password for fixing MIME attachment types";
var switchPrompt = "Do you want to switch off features requiring password completely";
var prefName = BTSPrefNS+"withoutPassowrd";
var domain = window.location.protocol + "//" + window.location.hostname;
var pass = passUtils.getPassword(login,
domain, BTSPassRealm);
var retObject = {
password: null,
withoutPass: false
};
// pass === null means no appropriate password in the storage
if (!preferences.get(prefName,false) && (pass === null)) {
passwordText = prompts.promptPassword(passPrompt);
if (passwordText && passwordText.length > 0) {
passUtils.setLogin(login, passwordText, domain,
BTSPassRealm);
retObject.password = passwordText;
} else {
var switchOff = prompts.promptYesNoCancel(switchPrompt);
if (switchOff) {
preferences.set(prefName,true);
}
retObject.withoutPass = switchOff;
}
} else {
retObject.password = pass;
}
callback(new Message("RetPassword", retObject));
};
exports.changeJSONURL = function changeJSONURL() {
var prfNm = BTSPrefNS+"JSONURL";
var url = preferences.get(prfNm,"");
var reply = prompts.prompt("New location of JSON configuration file", url);
if (reply) {
preferences.set(prfNm, reply.trim());
// TODO Restartless add-on needs to resolve this.
prompts.alert("For now, you should really restart Firefox!");
}
};
/**
*
libbz.getInstalledPackages(msg.data, function (pkgsMsg) {
worker.postMessage(pkgsMsg);
*/
exports.getInstalledPackages = function getInstalledPackages(location, config, callback) {
var installedPackages = {};
var enabledPackages = [];
if (typeof location == "string") {
location = new urlMod.URL(location);
}
console.log("location = " + location);
console.log("typeof location = " + typeof location);
// Collect enabled packages per hostname (plus default ones)
if (config.gJSONData && ("commentPackages" in config.gJSONData)) {
if ("enabledPackages" in config.gJSONData.configData) {
var epObject = config.gJSONData.configData.enabledPackages;
if (location.host in epObject) {
enabledPackages = enabledPackages.concat(epObject[location.host].split(/[,\s]+/));
}
if ("any" in epObject) {
enabledPackages = enabledPackages.concat(epObject.any.split(/[,\s]+/));
}
}
if ((enabledPackages.length === 1) && (enabledPackages[0] === "all")) {
enabledPackages = [];
for (var key in config.gJSONData.commentPackages) {
enabledPackages.push(key);
}
}
// TODO To be decided, whether we cannot just eliminate packages in
// installedPackages and having it just as a plain list of all cmdObjects.
enabledPackages.forEach(function (pkg, idx, arr) {
if (pkg in config.gJSONData.commentPackages) {
installedPackages[pkg] = config.gJSONData.commentPackages[pkg];
}
});
}
// Expand commentIdx properties into full comments
var cmdObj = {};
for (var pkgKey in installedPackages) {
for (var cmdObjKey in installedPackages[pkgKey]) {
cmdObj = installedPackages[pkgKey][cmdObjKey];
if ("commentIdx" in cmdObj) {
cmdObj.comment = config.gJSONData.commentStrings[cmdObj.commentIdx];
delete cmdObj.commentIdx;
}
}
}
callback(new Message("CreateButtons", {
instPkgs: installedPackages,
constData: config.constantData,
kNodes: config.gJSONData.configData.killNodes
}));
};
exports.getClipboard = function getClipboard(command, cb) {
cb(new Message("RetClipboard", {
text: clipboard.get(),
cmd: command
}));
};
exports.openURLinNewTab = function openURLinNewTab(urlStr) {
tabs.open({
url: urlStr,
inBackground: true,
onReady: function (t) {
t.activate();
}
});
};
exports.initialize = function initialize(config, callback) {
var prefName = BTSPrefNS+"JSONURL";
var urlStr = "";
if (preferences.isSet(prefName)) {
urlStr = preferences.get(prefName);
} else {
urlStr = JSONURLDefault;
preferences.set(prefName, JSONURLDefault);
}
// Randomize URL to avoid caching
// TODO see https://fedorahosted.org/bugzilla-triage-scripts/ticket/21
// for more thorough discussion and possible further improvement
urlStr += (urlStr.match(/\?/) == null ? "?" : "&") + (new Date()).getTime();
Request({
url: urlStr,
onComplete: function (response) {
if (response.status == 200) {
config.gJSONData = response.json;
// Get additional tables
if ("downloadJSON" in config.gJSONData.configData) {
var URLsList = config.gJSONData.configData.downloadJSON;
var dwnldObj = "";
URLsList.forEach(function (arr) {
var title = arr[0];
var url = arr[1];
Request({
url: url,
onComplete: function(response) {
if (response.status == 200) {
config.gJSONData.constantData[title] = response.json;
}
}
}).get();
});
}
// config.logger = new logger.Logger(JSON.parse(self.data.load("bugzillalabelAbbreviations.json")));
config.matches = config.gJSONData.configData.matches;
config.skipMatches = config.matches.map(function(x) {
return x.replace("show_bug.cgi.*","((process|post)_bug|attachment)\.cgi$");
});
config.objConstructor = {};
// var bzType = config.gJSONData.configData.objectStyle;
// if (bzType === "RH") {
// config.objConstructor = require("rhbzpage").RHBugzillaPage;
// } else if (bzType === "MoFo") {
// }
// config.objConstructor = require("mozillabzpage").MozillaBugzilla;
// callback(config);
config.constantData = {};
// TODO this is important and missing
if ("constantData" in config.gJSONData) {
config.constantData = config.gJSONData.constantData;
config.constantData.queryUpstreamBug = JSON.parse(
selfMod.data.load("queryUpstreamBug.json"));
config.constantData.XMLRPCData = JSON.parse(
selfMod.data.load("XMLRPCdata.json"));
}
if ("CCmaintainer" in config.constantData) {
config.defBugzillaMaintainerArr = config.constantData.CCmaintainer;
}
if ("suspiciousComponents" in config.gJSONData.configData) {
config.suspiciousComponents = config.gJSONData.configData.suspiciousComponents;
}
if ("XorgLogAnalysis" in config.gJSONData.configData) {
config.xorglogAnalysis = config.gJSONData.configData.XorgLogAnalysis;
}
if ("submitsLogging" in config.gJSONData.configData &&
config.gJSONData.configData.submitsLogging) {
logger.initialize(JSON.parse(selfMod.data.load(
"bugzillalabelAbbreviations.json")));
}
}
callback();
}
}).get();
}