aboutsummaryrefslogblamecommitdiffstats
path: root/lib/libbugzilla.js
blob: ceea270ea944b4ad61b6eeb8b35c36f3984fb4da (plain) (tree)
















































































































































































































































































                                                                                                                                                                                                                                              
/*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 JSONURLDefault = "https://fedorahosted.org/released"+
    "/bugzilla-triage-scripts/Config_data.json";
var BTSPrefNS = "bugzilla-triage.setting.";
var BTSPassRealm = "BTSXMLRPCPass";

var config = {};

/**
 * 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, callback) {
    var installedPackages = {};
    var enabledPackages = [];

    // 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.hostname in epObject) {
                enabledPackages = enabledPackages.concat(epObject[location.hostname].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
    installedPackages.forEach(function (pkg) {
        pkg.forEach(function (cmdObj) {
            if ("commentIdx" in cmdObj) {
                cmdObj.comment = config.commentStrings[cmdObj.commentIdx];
                delete cmdObj.commentIdx;                
            }
        });
    });
    callback(new Message("CreateButtons", {
        instPkgs: installedPackages,
        constData: config.constantData
    }));
};

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();
        }
    });
};

function initialize() {
    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) {
                    config.log = config.logger;
                    // FIXME this.setUpLogging();
                }

                if ("killNodes" in config.gJSONData.configData &&
                    window.location.hostname in config.gJSONData.configData.killNodes) {
                        var killConf = config.gJSONData.configData.killNodes[window.location.hostname];
                        util.killNodes(config.doc, killConf[0], killConf[1]);
                }

           }
        }
    }).get();
}