'
);
// Item with children
else {
// We display the waiting element
$(pathID + ' .disco-wait .disco-category-title').after(
'
' +
'' +
'
' + itemHost + '
' +
'
' + Common._e("Requesting this service...") + '
' +
'
'
);
// We display the category
$('#' + target + ' .disco-wait').show();
// We ask the server what's the service type
self.getType(itemHost, itemNode, sessionID);
}
});
}
// Else, there are no items for this query
else
self.noResult(pathID);
}
else if((type == 'muc') || (type == 'search') || (type == 'subscribe') || ((type == 'command') && $(handleXML).find('command').attr('xmlns'))) {
// Get some values
var xCommand = $(handleXML).find('command');
var bNode = xCommand.attr('node');
var bSession = xCommand.attr('sessionid');
var bStatus = xCommand.attr('status');
var xRegister = $(handleXML).find('query[xmlns="' + NS_REGISTER + '"]').text();
var xElement = $(handleXML).find('x');
// Search done
if((xElement.attr('type') == 'result') && (type == 'search')) {
var bPath = pathID;
// Display the result
$(handleXML).find('item').each(function() {
// Have some "flexibility" for what regards field names, it would be better to return the whole original DF
// layout, but on a large amount of result which have many fields, there's a very high chance the browser can
// choke on old systems or new ones even.
// Search for useful fields, return first result. This is rather hacky, but jQuery is horrible when it comes to
// matching st. using patterns. (TODO: Improve and return the full DF layout without choking the browser)
var bName;
var bCountry;
var doneName, doneCountry;
$.each($(this).find('field'), function(i, item)
{
var $item = $(item);
if ($(item).attr('var').match(/^(fn|name|[^n][^i][^c][^k]name)$/gi) && doneName !== true) {
bName = $item.children('value:first').text();
doneName = true;
} else if ($(item).attr('var').match(/^(ctry|country.*)$/gi) && doneCountry !== true) {
bCountry = $item.children('value:first').text();
doneCountry = true;
}
});
var bXID = $(this).find('field[var="jid"] value:first').text();
var dName = bName;
// Override "undefined" value
if(!bXID)
bXID = '';
if(!bName)
bName = Common._e("Unknown name");
if(!bCountry)
bCountry = Common._e("Unknown country");
// User hash
var bHash = hex_md5(bXID);
// HTML code
var bHTML = '
' +
'
' +
'' +
'
' +
'
' + bName + '
' +
'
' + bCountry + '
' +
'
' + bXID + '
' +
'
';
// The buddy is not in our buddy list?
if(!Common.exists('#roster .buddy[data-xid="' + escape(bXID) + '"]'))
bHTML += '' + Common._e("Add") + '';
// Chat button, if not in welcome/directory mode
if(target == 'discovery')
bHTML += '' + Common._e("Chat") + '';
// Profile button, if not in discovery mode
else
bHTML += '' + Common._e("Profile") + '';
// Close the HTML element
bHTML += '
'
);
});
}
// Default text
else
$(pathID).append('
' + Common._e("Your form has been sent.") + '
');
// Display the back button
self.buttons(type, 'back', sessionID, from, '', '', target, pathID);
// Add the gateway to our roster if subscribed
if(type == 'subscribe')
Roster.addThisContact(from);
}
// Command canceled
else if((bStatus == 'canceled') && (type == 'command')) {
if(target == 'discovery')
Discovery.start();
else if(target == 'adhoc')
dataForm(from, 'command', '', '', 'adhoc');
}
// No items for this query
else
self.noResult(pathID);
}
else if(type == 'command') {
if($(handleXML).find('item').attr('jid')) {
// We display the elements
$(handleXML).find('item').each(function() {
// We parse the received xml
var itemHost = $(this).attr('jid');
var itemNode = $(this).attr('node');
var itemName = $(this).attr('name');
var itemHash = hex_md5(itemHost);
// We display the waiting element
$(pathID).prepend(
'
' +
'
' + itemName + '
' +
'
»
' +
'
'
);
});
}
// Else, there are no items for this query
else
self.noResult(pathID);
}
}
// Focus on the first input
$(document).oneTime(10, function() {
$(pathID + ' input:visible:first').focus();
});
// Hide the wait icon
$('#' + target + ' .wait').hide();
} catch(e) {
Console.error('DataForm.handleContent', e);
}
};
/**
* Fills the dataform elements
* @public
* @param {type} xml
* @param {type} id
* @return {boolean}
*/
self.fill = function(xml, id) {
/* REF: http://xmpp.org/extensions/xep-0004.html */
try {
// Initialize new vars
var target = id.split('-')[0];
var pathID = '#' + target + ' .results[data-session="' + id + '"]';
var selector, is_dataform;
// Is it a dataform?
if($(xml).find('x[xmlns="' + NS_XDATA + '"]').size())
is_dataform = true;
else
is_dataform = false;
// Determines the good selector to use
if(is_dataform)
selector = $(xml).find('x[xmlns="' + NS_XDATA + '"]');
else
selector = $(xml);
// Form title
selector.find('title').each(function() {
$(pathID).append(
'
' + $(this).text().htmlEnc() + '
'
);
});
// Form instructions
selector.find('instructions').each(function() {
$(pathID).append(
'
' + $(this).text().htmlEnc() + '
'
);
});
// Register?
if(!is_dataform) {
// Items to detect
var reg_names = [Common._e("Nickname"), Common._e("Name"), Common._e("Password"), Common._e("E-mail")];
var reg_ids = ['username', 'name', 'password', 'email'];
// Append these inputs
$.each(reg_names, function(a) {
selector.find(reg_ids[a]).each(function() {
$(pathID).append(
'
' +
'' +
'' +
'
'
);
});
});
return false;
}
// Dataform?
selector.find('field').each(function() {
// We parse the received xml
var type = $(this).attr('type');
var label = $(this).attr('label');
var field = $(this).attr('var');
var value = $(this).find('value:first').text();
var required = '';
// No value?
if(!field)
return;
// Required input?
if($(this).find('required').size())
required = ' required=""';
// Compatibility fix
if(!label)
label = field;
if(!type)
type = '';
// Generate some values
var input;
var hideThis = '';
// Fixed field
if(type == 'fixed')
$(pathID).append('
' + value.htmlEnc() + '
');
else {
// Hidden field
if(type == 'hidden') {
hideThis = ' style="display: none;"';
input = '';
}
// Boolean field
else if(type == 'boolean') {
var checked;
if(value == '1')
checked = 'checked';
else
checked = '';
input = '';
}
// List-single/list-multi field
else if((type == 'list-single') || (type == 'list-multi')) {
var multiple = '';
// Multiple options?
if(type == 'list-multi')
multiple = ' multiple=""';
// Append the select field
input = '';
}
// Text-multi field
else if(type == 'text-multi')
input = '';
// JID-multi field
else if(type == 'jid-multi') {
// Put the XID into an array
var xid_arr = [];
$(this).find('value').each(function() {
var cValue = $(this).text();
if(!Utils.existArrayValue(xid_arr, cValue))
xid_arr.push(cValue);
});
// Sort the array
xid_arr.sort();
// Create the input
var xid_value = '';
if(xid_arr.length) {
for(var i in xid_arr) {
// Any pre-value
if(xid_value)
xid_value += ', ';
// Add the current XID
xid_value += xid_arr[i];
}
}
input = '';
}
// Other stuffs that are similar
else {
// Text-single field
var iType = 'text';
// Text-private field
if(type == 'text-private')
iType = 'password';
// JID-single field
else if(type == 'jid-single')
iType = 'email';
input = '';
}
// Append the HTML markup for this field
$(pathID).append(
'
' +
'' +
input +
'
'
);
}
});
} catch(e) {
Console.error('DataForm.fill', e);
} finally {
return false;
}
};
/**
* Gets the dataform type
* @public
* @param {string} host
* @param {string} node
* @param {string} id
* @return {undefined}
*/
self.getType = function(host, node, id) {
try {
var iq = new JSJaCIQ();
iq.setID(id + '-' + genID());
iq.setTo(host);
iq.setType('get');
var iqQuery = iq.setQuery(NS_DISCO_INFO);
if(node) {
iqQuery.setAttribute('node', node);
}
con.send(iq, self.handleThisBrowse);
} catch(e) {
Console.error('DataForm.getType', e);
}
};
/**
* Handles the browse stanza
* @public
* @param {object} iq
* @return {undefined}
*/
self.handleThisBrowse = function(iq) {
/* REF: http://xmpp.org/registrar/disco-categories.html */
try {
var id = iq.getID();
var splitted = id.split('-');
var target = splitted[0];
var sessionID = target + '-' + splitted[1];
var from = Common.fullXID(Common.getStanzaFrom(iq));
var hash = hex_md5(from);
var handleXML = iq.getQuery();
var pathID = '#' + target + ' .results[data-session="' + sessionID + '"]';
// We first remove the waiting element
$(pathID + ' .disco-wait .' + hash).remove();
if($(handleXML).find('identity').attr('type')) {
var category = $(handleXML).find('identity').attr('category');
var type = $(handleXML).find('identity').attr('type');
var named = $(handleXML).find('identity').attr('name');
if(named)
gName = named;
else
gName = '';
var one, two, three, four, five;
// Get the features that this entity supports
var findFeature = $(handleXML).find('feature');
for(var i in findFeature) {
var current = findFeature.eq(i).attr('var');
switch(current) {
case NS_SEARCH:
one = 1;
break;
case NS_MUC:
two = 1;
break;
case NS_REGISTER:
three = 1;
break;
case NS_COMMANDS:
four = 1;
break;
case NS_DISCO_ITEMS:
five = 1;
break;
default:
break;
}
}
var buttons = Array(one, two, three, four, five);
// We define the toolbox links depending on the supported features
var tools = '';
var aTools = Array('search', 'join', 'subscribe', 'command', 'browse');
var bTools = Array(Common._e("Search"), Common._e("Join"), Common._e("Subscribe"), Common._e("Command"), Common._e("Browse"));
for(var b in buttons) {
if(buttons[b]) {
tools += '';
}
}
// As defined in the ref, we detect the type of each category to put an icon
switch(category) {
case 'account':
case 'auth':
case 'automation':
case 'client':
case 'collaboration':
case 'component':
case 'conference':
case 'directory':
case 'gateway':
case 'headline':
case 'hierarchy':
case 'proxy':
case 'pubsub':
case 'server':
case 'store':
break;
default:
category = 'others';
}
// We display the item we found
$(pathID + ' .disco-' + category + ' .disco-category-title').after(
'