var CC = Components.Constructor;
var LoginManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
var LoginInfo = new CC("@mozilla.org/login-manager/loginInfo;1",Ci.nsILoginInfo,"init");
/**
* Static Object containig metadata of the creator and of the command
*/
var MetaData = {
icon : 'http://www.bugzilla.org/img/bugzilla_icon.png',
homepage : 'http://rfobic.blogspot.com/2008/10/ubiquity-command-for-bugzilla.html',
author : { name: "Irakli Gozalishvili", email: "Irakli.Gozalishvili@tomtom.com"}
};
var Session = function(nick, url, username, password) {
this.nick = nick;
// creating new session
if (url && username && password) {
// remove login if exists
this.remove();
// creating instance of nsILoginInfo
var login = new LoginInfo(url, null, nick, username, password, '', '');
// adding / changeing Bugzilla xml-rpc url for session
Bugzilla._prefs.setValue(Bugzilla._prefNames.url + nick, url);
// adding session to bookmarks
Bugzilla._prefs.setValue(Bugzilla._prefNames.sessions, Bugzilla._prefs.getValue(Bugzilla._prefNames.sessions,'') + Bugzilla._prefNames.splitter + nick);
// storing user and password
LoginManager.addLogin(login);
}
};
Session.prototype = {
/**
* Session name
* @type {string}
*/
nick : null,
/**
* Url of the Bugzilla XML-RPC service for this session
* @type {String}
*/
get url() {
return Bugzilla._prefs.getValue(Bugzilla._prefNames.url + this.nick, '');
},
/**
* getter for a user and password
* @type {Object}
* { username : 'MyUeser', password : 'myPassword'}
*/
get login() {
var logins = LoginManager.findLogins({}, this.url, null, this.nick);
return logins.length > 0 ? {username : logins[0].username, password : logins[0].password} : null;
},
/**
* Removes current login from memory
*/
remove : function() {
// removeing from stored sessions
Bugzilla._prefs.setValue(Bugzilla._prefNames.sessions, Bugzilla._prefs.getValue(Bugzilla._prefNames.sessions,'').replace(Bugzilla._prefNames.splitter + this.nick, ''));
// removeing login info from LoginManager
var logins = LoginManager.findLogins({}, this.url, null, this.nick);
for (var i = 0; i < logins.length; i++) {
LoginManager.removeLogin(logins[i]);
}
}
};
var Bugzilla = {
/**
* Last accessed session
* @type {Object}
* {
* url : 'https://bugzilla.mozilla.org/xmlrpc.cgi',
* user : 'myUser',
* password : 'myPassword'
* }
*/
_lastSession : null,
get lastSession() {
if (!this._lastSession) {
var lastSessionName = this._prefs.getValue(this._prefNames.lastSession, null);
this._lastSession = lastSessionName ? new Session(lastSessionName) : null;
}
return this._lastSession;
},
set lastSession(session) {
this._prefs.setValue(this._prefNames.lastSession, session.nick);
this._lastSession = session;
},
_prefs : Application.prefs,
/**
* Map of preference names
*/
_prefNames : {
splitter : '|',
sessions : 'ubiquity.commands.bugzilla.sessions',
url : 'ubiquity.commands.bugzilla.url.',
lastSession : 'ubiquity.commands.bugzilla.lastSession'
},
/**
* Makes rpc calls to the JIRA XML-RPC Service and returns results as XML
* Example:
* rpc('http://jira.atlassian.com/rpc/xmlrpc','jira1.login',
*
*
* {user}
*
*
* {password}
*
* );
*
*
* @param url {String} XML-RPC Service url
* @param method {String} Name of the method to be called
* @param data {XML} Data to be passed to the Remote Procedure
*
* @throws Error {Error} Throw exceprion if method responce contains fault
*/
rpc : function(url, method, data) {
var methodResponce = this.rpc2json(new XML(jQuery.ajax({
url : url,
type : 'POST',
data :
{method}
{this.json2rpc(data)}
.toXMLString(),
async : false,
contentType : 'text/xml',
dataType : 'xml'
}).responseText.replace(/^<\?xml\s+version\s*=\s*(["'])[^\1]+\1[^?]*\?>/,"")));
if (methodResponce.fault) {
throw methodResponce;
} else {
return methodResponce;
}
},
/**
* Recursive function converts responce of the RPC
* call to the JSON Object
* @returns {Object} JSON type object
*/
rpc2json : function(xml) {
var self = arguments.callee;
var data = {};
for each (var member in xml.*) {
if (member.nodeKind() == 'text')
return new String(member);
switch (member.name().toString()) {
case 'i4' :
case 'int' :
case 'double' :
return new Number(member.text());
break;
case 'string' :
return new String(member.text());
break;
case 'dateTime.iso8601' :
return new Date(member.text());
break;
case 'base64' :
return member.text();
break;
case 'value' :
case 'struct' :
case 'methodResponse' :
return self(member);
break;
case 'member' :
data[member.name.text()] = self(member.value);
break;
case 'fault' :
case 'params' :
case 'param' :
data[member.name().toString()] = self(member);
break;
case 'array' :
var tempArray = [];
for each (value in member.data.value) {
tempArray.push(self(value));
}
return tempArray;
break;
default :
return null;
}
}
return data;
},
/**
* Recursive function converts JSON type object to RPC method call like xml
* @returns {XML} E4X object
*/
json2rpc : function(json) {
var self = arguments.callee;
if (!json) return
switch (typeof json) {
case 'boolean':
return {((json) ? '1' : '0')};
case 'number':
return (parseInt(json) == json) ? {json} : {json};
case 'string':
return {json};
case 'object':
if (json instanceof String)
return {json};
else if (json instanceof Date)
return {json.getFullYear() + json.getMonth() + json.getDate() + 'T' + json.getHours() + ':' + json.getMinutes() + ':' + json.getSeconds()};
else if (json instanceof Array) {
if (self == self.caller) {
var tempArray = ;
for each(member in json)
tempArray.data.appendChild({self(member)});
return tempArray;
} else {
result =
for each(member in json)
result.appendChild({self(member)});
return result;
}
} else {
var struct = ;
for (key in json)
struct.appendChild(
{key}
{self(json[key])}
);
return struct;
}
break;
}
},
/**
* Makes login to the JIRA XML-RPC Service and stores session id in the session memebr.
* @private
* @param user {String} Username
* @param password {String}
* @returns {void}
*/
_login : function(user, password) {
try {
this._session = this.rpc2json(this.rpc(this.url, 'jira1.login',
{user}
{password}
).params.param);
} catch (e) {
if (e instanceof XML)
displayMessage(e.fault.value.struct.member.value[0]);
else
displayMessage(e.toString());
}
},
getIssue : function(key) {
try {
return this.rpc2json(this.rpc(this.url, 'jira1.getIssue',
{this.session}
{key}
).params.param);
} catch (e) {
if (e instanceof XML)
displayMessage(e.fault.value.struct.member.value[0]);
else
displayMessage(e.toString());
}
},
getInfo : function() {
try {
return this.rpc(Bugzilla.lastSession.url, 'Bugzilla.version').params.param.version;
} catch (e if e.fault && e.fault.faultString) {
displayMessage(e.fault.faultString);
} catch (e) {
displayMessage(e);
}
},
getUsers : function(params) {
try {
dump('\n\n');
dump(this.rpc(Bugzilla.lastSession.url, 'User.get', params).toSource());
dump('\n\n');
} catch (e if e.fault && e.fault.faultString) {
displayMessage(e.fault.faultString.toString());
dump('\nError> ' + e.fault.faultString);
} catch (e) {
displayMessage(e);
}
},
getBugs : function(params) {
try {
return this.rpc(Bugzilla.lastSession.url, 'Bug.get_bugs', params).params.param.bugs;
} catch (e if e.fault && e.fault.faultString) {
displayMessage(e.fault.faultString.toString());
dump('\nError> ' + e.fault.faultString);
dump('\nError> ' + e.toSource());
} catch (e) {
displayMessage(e);
dump('\nError> ' + e.stack);
}
}
};
Bugzilla.nouns = {
session : {
_name : 'Session',
suggest : function(text, html) {
var sessions = Bugzilla._prefs.getValue(Bugzilla._prefNames.sessions, '').split(Bugzilla._prefNames.splitter);
var filter = new RegExp('[\s\S]*' + text + '[\s\S]*','i');
var matchedsuggestions = [];
var unmatchedSuggestions = [];
for each (var session in sessions) {
var suggestions = filter.test(session) ? matchedsuggestions : unmatchedSuggestions;
suggestions.push({
text : session,
summary : session,
html : session,
data : new Session(session)
});
}
return matchedsuggestions.length ? matchedsuggestions : unmatchedSuggestions;
},
default : function() {
if (Bugzilla.lastSession)
return {
text : Bugzilla.lastSession.nick,
summary : Bugzilla.lastSession.nick,
html : Bugzilla.lastSession.nick,
data : Bugzilla.lastSession
};
}
},
bugByID : {
_name : 'Bug',
suggest : function(text, html) {
var suggestions = [];
var bugs = Bugzilla.getBugs([{ids : text.split(/\s+/), permissive : true}]);
for each (var bug in bugs) {
suggestions.push({
text : bug.internals.bug_id,
summary : bug.internals.bug_id,
html : bug.internals.bug_id,
data : bug
});
}
return suggestions;
},
default : function() {
return {
text : 'No bugs being found',
summary : 'No bugs being found',
html : '',
data : {}
};
}
}
};
CmdUtils.CreateCommand({
name : 'bugzilla-session-add',
icon : MetaData.icon,
description : 'Creates and stores new session',
author : MetaData.author,
homepage : MetaData.homepage,
help : 'type bugzilla-add-session name url user password',
modifiers : {
'name' : noun_arb_text,
'url' : noun_arb_text,
'user' : noun_arb_text,
'password' : noun_arb_text
},
preview : function(pblock, takes, modifiers) {
[name, url, username, password] = [modifiers.name.text, modifiers.url.text, modifiers.user.text, modifiers.password.text];
var error = 'color: red';
var input = 'background: none; border: none; color: white; font-size: 12px;';
var link = 'text-decoration: underline;'
pblock.innerHTML =
{'Creates and saves new session Bugzilla:'}
{ 'Session name : '}
{ name ? {name} : {'Needs a name'} }
{ 'Bugzilla URL : '}
{ url ?
{url} :
{'Needs url'}}
{ 'User : '}
{ username ? : {'Needs user name'}}
{ 'password : '}
{ password ? : {'Needs password'}}
.toXMLString();
},
execute : function(takes, modifiers) {
[name, url, username, password] = [modifiers.name.text, modifiers.url.text || takes.text, modifiers.user.text, modifiers.password.text];
try {
if (name && url && username && password)
var session = new Session(name, url, username, password);
if (!Bugzilla.lastSession) {
Bugzilla.lastSession = session;
}
} catch(e) {
displayMessage(e.toSource());
}
}
});
CmdUtils.CreateCommand({
name : 'bugzilla-session-remove',
icon : MetaData.icon,
description : 'Removes selected session from memory',
author : MetaData.author,
homepage : MetaData.homepage,
help : 'type bugzilla-session-remove name',
takes : {
'session' : Bugzilla.nouns.session,
},
preview : function(pblock, takes) {
var error = 'color: red';
var input = 'background: none; border: none; color: white; font-size: 12px;';
var link = 'text-decoration: underline;'
pblock.innerHTML =
{'Removes Bugzilla session :'}
{ takes.text }
.toXMLString();
},
execute : function(takes) {
try {
(new Session(takes.text)).remove();
} catch(e) {
displayMessage(e.toSource());
}
}
});
CmdUtils.CreateCommand({
name : 'bugzilla-info-version',
icon : MetaData.icon,
description : 'Gets bugzilla version',
author : MetaData.author,
homepage : MetaData.homepage,
help : 'type bugzilla-info-version',
modifiers : {
'session' : Bugzilla.nouns.session,
},
previewDelay : 200,
preview : function(pblock, takes, modifiers) {
Bugzilla.lastSession = modifiers.session.data;
pblock.innerHTML =
{'Bugzilla information : '+ modifiers.session.text}
{ 'Version : '}
{ Bugzilla.getInfo() }
.toXMLString();
},
execute : function(takes, modifiers) {}
});
CmdUtils.CreateCommand({
name : 'bugzilla-user',
icon : MetaData.icon,
description : 'Gets information about user accounts in Bugzilla',
author : MetaData.author,
homepage : MetaData.homepage,
//help : 'type bugzilla-info-version',
modifiers : {
'id' : noun_arb_text,
'name' : noun_arb_text,
'match' : noun_arb_text,
'session' : Bugzilla.nouns.session,
},
previewDelay : 200,
preview : function(pblock, takes, modifiers) {
Bugzilla.lastSession = modifiers.session.data;
pblock.innerHTML =
{'User information : '+ modifiers.id.text}
{ 'Version : '}
{Bugzilla.getUsers({
params : {
param : {
ids : modifiers.id.text.split('|')
}
}
})}
.toXMLString();
},
execute : function(takes, modifiers) {}
});
CmdUtils.CreateCommand({
name : 'bugzilla-get',
icon : MetaData.icon,
description : 'Gets information about particular bugs in the database.',
author : MetaData.author,
homepage : MetaData.homepage,
//help : 'type bugzilla-info-version',
takes : {
'id' : Bugzilla.nouns.bugByID
},
modifiers : {
'session' : Bugzilla.nouns.session,
},
previewDelay : 300,
preview : function(pblock, takes, modifiers) {
Bugzilla.lastSession = modifiers.session.data;
var bug = takes.data.internals;
pblock.innerHTML =
{'Bug '+ bug.bug_id}
{bug.short_desc}
{bug.resolution ?
{'Resolution : '}{bug.resolution}
: ''}
{bug.version ?
{'Version : '}{bug.version}
: ''}
{bug.version ?
{'Target Milestone : '}{bug.target_milestone}
: ''}
{bug.version ?
{'Status : '}{bug.bug_status}
: ''}
{bug.version ?
{'Priority : '}{bug.priority}
: ''}
{bug.version ?
{'Severity : '}{bug.bug_severity}
: ''}
{bug.version ?
{'Platform : '}{bug.rep_platform}
: ''}
{bug.version ?
{'OS : '}{bug.op_sys}
: ''}
{bug.bug_file_loc != '' ?
: ''}
.toXMLString();
},
execute : function(takes, modifiers) {}
});