/*
* Copyright 2006-2010 Daniel Henninger. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package net.sf.kraken.web;
import net.sf.kraken.KrakenPlugin;
import net.sf.kraken.registration.Registration;
import net.sf.kraken.registration.RegistrationManager;
import net.sf.kraken.type.TransportType;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.PluginManager;
import org.xmpp.packet.JID;
import org.apache.log4j.Logger;
import java.util.*;
/**
* This provides the conduit through which all XMLRPC interface actions occur.
*
* @author Daniel Henninger
*/
public class XMLRPCConduit {
static Logger Log = Logger.getLogger(XMLRPCConduit.class);
ConfigManager configManager = new ConfigManager();
public String authPassword = null;
public XMLRPCConduit() {
authPassword = JiveGlobals.getProperty("plugin.gateway.xmlrpc.password", null);
}
public void destroy() {
authPassword = null;
}
private boolean verifyPassword(String password) {
if (authPassword == null) {
Log.error("XML-RPC authentication not set up on server.");
return false;
}
if (!authPassword.equals(password)) {
Log.warn("Unauthorized attempt on XML-RPC interface.");
return false;
}
return true;
}
/**
* Toggles whether a transport is enabled or disabled.
*
* @param password Auth password for making changes
* @param transportName Name of the transport to be enabled or disabled (type of transport)
* @return True or false if the transport is enabled after this call.
*/
public boolean toggleTransport(String password, String transportName) {
if (verifyPassword(password)) {
return configManager.toggleTransport(transportName);
}
else {
return false;
}
}
/**
* Adds a new registration
*
* @param password Auth password for making changes
* @param user Username or full JID of user who is getting an account registered.
* @param transportType Type of transport to add user to.
* @param legacyUsername User's username on the legacy service.
* @param legacyPassword User's password on the legacy service.
* @param legacyNickname User's nickname on the legacy service.
* @return Error message or "Success" on success.
*/
public String addRegistration(String password, String user, String transportType, String legacyUsername, String legacyPassword, String legacyNickname) {
if (!verifyPassword(password)) {
return "Authorization failed!";
}
String results = configManager.addRegistration(user, transportType, legacyUsername, legacyPassword, legacyNickname);
if (results == null) {
return "Success";
}
else {
return results;
}
}
/**
* Deletes a registration.
*
* @param password Auth password for making changes
* @param user Username or full JID of user who is getting an account deleted.
* @param transportType Type of transport to add user to.
* @return Error message or "Success" on success.
*/
public String deleteRegistration(String password, String user, String transportType) {
if (!verifyPassword(password)) {
return "Authorization failed!";
}
JID jid;
if (user.contains("@")) {
jid = new JID(user);
}
else {
jid = new JID(user, XMPPServer.getInstance().getServerInfo().getXMPPDomain(), null);
}
Collection<Registration> registrations = RegistrationManager.getInstance().getRegistrations(jid, TransportType.valueOf(transportType));
if (registrations.isEmpty()) {
// User is not registered with us.
return "Unable to find registration to delete.";
}
Registration registration = registrations.iterator().next();
String results = configManager.deleteRegistration((int)registration.getRegistrationID());
if (results == null) {
return "Success";
}
else {
return results;
}
}
/**
* Updates a registration.
*
* @param password Auth password for making changes
* @param user Username or full JID of user who is getting an account updated.
* @param transportType Type of transport to add user to.
* @param legacyUsername User's username on the legacy service.
* @param legacyPassword User's password on the legacy service.
* @param legacyNickname User's nickname on the legacy service.
* @return Error message or "Success" on success.
*/
public String updateRegistration(String password, String user, String transportType, String legacyUsername, String legacyPassword, String legacyNickname) {
if (!verifyPassword(password)) {
return "Authorization failed!";
}
JID jid;
if (user.contains("@")) {
jid = new JID(user);
}
else {
jid = new JID(user, XMPPServer.getInstance().getServerInfo().getXMPPDomain(), null);
}
Collection<Registration> registrations = RegistrationManager.getInstance().getRegistrations(jid, TransportType.valueOf(transportType));
if (registrations.isEmpty()) {
// User is not registered with us.
return "Unable to find registration to update.";
}
Registration registration = registrations.iterator().next();
String results = configManager.updateRegistration((int)registration.getRegistrationID(), legacyUsername, legacyPassword, legacyNickname);
if (results == null) {
return "Success";
}
else {
return results;
}
}
/**
* Retrieve a list of all active/enabled transports.
*
* @param password Auth password for making changes
* @return List of active transports.
*/
public List<String> getActiveTransports(String password) {
if (!verifyPassword(password)) {
return Arrays.asList("Authorization failed!");
}
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
KrakenPlugin plugin = (KrakenPlugin)pluginManager.getPlugin("kraken");
List<String> activeTransports = new ArrayList<String>();
for (String transport : plugin.getTransports()) {
if (plugin.serviceEnabled(transport)) {
activeTransports.add(transport);
}
}
return activeTransports;
}
/**
* Lists the currently registered transports for a given User.
* @param password Auth password for making changes
* @param user Username or full JID of user whose registrations should be listed
* @return a Collection of RegistrationBeans. In XML-RPC, this will convert into an array of structs.
*/
public Collection<RegistrationBean> getRegistrations(String password, String user) {
/*
* the redstone xml-rpc library can convert collections into xml-rpc arrays and
* load all properties from a java bean into an xml-rpc struct
*/
if (!verifyPassword(password)) {
return Collections.emptyList();
}
JID jid;
if (user.contains("@")) {
jid = new JID(user);
}
else {
jid = new JID(user, XMPPServer.getInstance().getServerInfo().getXMPPDomain(), null);
}
Collection<Registration> registrations = RegistrationManager.getInstance().getRegistrations(jid);
Collection<RegistrationBean> result = new LinkedList<RegistrationBean>();
/*
* copy the values of Registration objects
* into RegistrationBean objects. Unfortunately the Registration bean is too complex to send
* it directly. There is also a bug in redstone xml-rpc, it assumes that there is a getter for
* a property if there is a setter, too.
*/
for (Registration r: registrations) {
result.add(new RegistrationBean(r));
}
return result;
}
/**
* Lists the currently registered transports for all Users.
* @param password Auth password for making changes
* @return a Map of <user,Collection of RegistrationBeans>. In XML-RPC, this will convert into an array of structs.
*/
public Map<String, Collection<RegistrationBean>> getAllRegistrations(String password) {
/*
* the redstone xml-rpc library can convert collections into xml-rpc arrays and
* load all properties from a java bean into an xml-rpc struct
*/
if (!verifyPassword(password)) {
return null;
}
Collection<Registration> registrations = RegistrationManager.getInstance().getRegistrations();
Map<String, Collection<RegistrationBean>> result = new HashMap<String, Collection<RegistrationBean>>();
for(Registration reg : registrations) {
Collection<RegistrationBean> coll = result.get(reg.getJID().getNode());
if(coll == null) {
coll = new LinkedList<RegistrationBean>();
result.put(reg.getJID().getNode(), coll);
}
coll.add(new RegistrationBean(reg));
}
return result;
}
}