Commit 19486c49 authored by Daniel Henninger's avatar Daniel Henninger Committed by dhenninger

[GATE-39] Incorporated the work of Ravin Dimantha and Patrick Siu for initial SIP/SIMPLE support!

Replaces included sip icons with Ryans new ones.
Applied Ryan's suggestions for a better filter look/feel on the registrations page.
Added new library files to plugins.iml.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk/src/plugins/gateway@7107 b35dd754-fafc-0310-a699-88a17e54d16e
parent 0789ab69
File added
Name | Version
-------------------------------------------------------
cindy.jar | 2.4.4
concurrent.jar | 1.3.4
dwr.jar | 1.1.1 (patched [#3])
irclib.jar | 1.10
jainsipapi.jar | 1.2 (nightly 2007-02-13)
jainsipri.jar | 1.2 (nightly 2007-02-13)
jakarta-regexp.jar | 1.3
jml.jar | svn-20061216
joscar-client.jar | svn-20070204 (patched [#2])
joscar-common.jar | svn-20070204
joscar-protocol.jar | svn-20070204 (patched [#2])
log4j.jar | 1.2.8
picocontainer.jar | 1.2.0
ymsg_network.jar | 0.61 (patched [#1])
ymsg_support.jar | 0.61 (patched [#1])
......
......@@ -153,6 +153,17 @@
## Added key: 'gateway.base.registrationdeniedbadusername'
## Added key: 'gateway.web.settings.unstable.title'
## Added key: 'gateway.web.settings.unstable.notice'
##
## 1.0 Beta 8
## Added key: 'gateway.sip.shortservice'
## Added key: 'gateway.sip.service'
## Added key: 'gateway.sip.name'
## Added key: 'gateway.sip.username'
## Added key: 'gateway.sip.password'
## Added key: 'gateway.sip.registration'
## Added key: 'gateway.sip.passwordincorrect'
## Added key: 'gateway.sip.sendmsgfailed'
## Added key: 'gateway.sip.illegalaccount'
# Temporary Tags Until Fixed Properly
......@@ -242,6 +253,17 @@ gateway.irc.donotdisturb=Do Not Disturb
gateway.irc.errorreceived=IRC error received:
gateway.irc.errorreceivedwithcode=IRC error received (code {0}):
# SIP Transport
gateway.sip.shortservice=SIP
gateway.sip.service=SIMPLE
gateway.sip.name=SIMPLE Transport
gateway.sip.username=Username
gateway.sip.password=Password
gateway.sip.registration=Please enter your SIMPLE username and password.
gateway.sip.passwordincorrect=The password you registered with is incorrect. Please re-register with the correct password.
gateway.sip.sendmsgfailed=Unable to send SIMPLE message. Reason:
gateway.sip.illegalaccount=You are registered with the SIP/SIMPLE transport with an illegal account name.\nThe account name should look like an email address.\nYou registered as:
# Web Interface (Settings)
gateway.web.settings.instructions=Select which gateways will be allowed, what features are available, and who can connect to each gateway service. Checking a gateway enables the service.
gateway.web.settings.tests=Tests
......
......@@ -141,3 +141,12 @@ gateway.base.registrationdeniednoacct=Ihre Registrierung wurde verweigert, weil
gateway.base.registrationdeniedbadusername=Ihre Registrierung wurde verweigert, weil der von ihnen angegebene Benutzername fr diesen Service ungltig ist.
gateway.web.settings.unstable.title=Instabile Gateways
gateway.web.settings.unstable.notice=Die folgenden Gateways sind instabil und es wird nicht empfohlen diese in einer Produktionsumgebung einzusetzen. Sie werden bereitgestellt fr die, die interessiert sind instabile Dienste zu testen und wissen, da diese mglicherweise nicht richtig funktionieren.
gateway.sip.shortservice=SIP
gateway.sip.service=SIMPLE
gateway.sip.name=SIMPLE Transport
gateway.sip.username=Username
gateway.sip.password=Password
gateway.sip.registration=Please enter your SIMPLE username and password.
gateway.sip.passwordincorrect=The password you registered with is incorrect. Please re-register with the correct password.
gateway.sip.sendmsgfailed=Unable to send SIMPLE message. Reason:
gateway.sip.illegalaccount=You are registered with the SIP/SIMPLE transport with an illegal account name.\nThe account name should look like an email address.\nYou registered as:
\ No newline at end of file
......@@ -141,3 +141,12 @@ gateway.base.registrationdeniednoacct=u registraci\u00f3n fue denegada ya que no
gateway.base.registrationdeniedbadusername=Su registraci\u00f3n fue denegada ya que el nombre de usuario especificado no es v\u00e1lido para este servicio.
gateway.web.settings.unstable.title=Gateways Inestables
gateway.web.settings.unstable.notice=Los siguientes transportes estan inestables por lo que no se recomandienda su uso en ambientes de producci\u00f3n. Los mismos son provistos para aquellos que desean probar servicios inestables y que no tienen problema si los mismos no funcionan correctamente.
gateway.sip.shortservice=SIP
gateway.sip.service=SIMPLE
gateway.sip.name=SIMPLE Transport
gateway.sip.username=Username
gateway.sip.password=Password
gateway.sip.registration=Please enter your SIMPLE username and password.
gateway.sip.passwordincorrect=The password you registered with is incorrect. Please re-register with the correct password.
gateway.sip.sendmsgfailed=Unable to send SIMPLE message. Reason:
gateway.sip.illegalaccount=You are registered with the SIP/SIMPLE transport with an illegal account name.\nThe account name should look like an email address.\nYou registered as:
\ No newline at end of file
......@@ -141,3 +141,12 @@ gateway.base.registrationdeniednoacct=Seu registro foi negado porque voc
gateway.base.registrationdeniedbadusername=Seu registro foi negado pois o usurio fornecido no vlido para o servio.
gateway.web.settings.unstable.title=Gateways Instveis
gateway.web.settings.unstable.notice=Os gateways a seguir no so recomendados para ambientes de produo. Eles so disponibilizados para aqueles que desejam testar o servio mesmo sabendo que eles podem no funcionar corretamente.
gateway.sip.shortservice=SIP
gateway.sip.service=SIMPLE
gateway.sip.name=SIMPLE Transport
gateway.sip.username=Username
gateway.sip.password=Password
gateway.sip.registration=Please enter your SIMPLE username and password.
gateway.sip.passwordincorrect=The password you registered with is incorrect. Please re-register with the correct password.
gateway.sip.sendmsgfailed=Unable to send SIMPLE message. Reason:
gateway.sip.illegalaccount=You are registered with the SIP/SIMPLE transport with an illegal account name.\nThe account name should look like an email address.\nYou registered as:
\ No newline at end of file
......@@ -81,6 +81,10 @@ public class GatewayPlugin implements Plugin {
/* Set up MSN transport. */
transports.put("msn", new TransportInstance(TransportType.msn, LocaleUtils.getLocalizedString("gateway.msn.name", "gateway"), "org.jivesoftware.wildfire.gateway.protocols.msn.MSNTransport", componentManager));
maybeStartService("msn");
/* Set up SIP/SIMPLE transport. */
transports.put("sip", new TransportInstance(TransportType.sip, LocaleUtils.getLocalizedString("gateway.sip.name", "gateway"), "org.jivesoftware.wildfire.gateway.protocols.simple.SimpleTransport", componentManager));
maybeStartService("sip");
}
public void destroyPlugin() {
......
package org.jivesoftware.wildfire.gateway.protocols.simple;
import java.io.ByteArrayInputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.util.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xmpp.packet.Presence;
/**
* This class performs conversions between presence packets of XMPP and SIMPLE formats.
* <br>
* By now, SIP presence comforms with <a href="http://www.ietf.org/rfc/rfc4480.txt">RFC4480</a>.
* @author Patrick Siu
* @version 0.0.1
*/
public class SimplePresence {
/**
* Tuple status of the presence packet.
* @author Patrick Siu
* @version 0.0.1
*/
public enum TupleStatus {
OPEN ("open"),
CLOSED("closed");
private String status;
public static TupleStatus getTupleStatus(String tupleStatusString) throws IllegalArgumentException {
for (TupleStatus t : values()) {
if (t.toString().equalsIgnoreCase(tupleStatusString)) return t;
}
throw new IllegalArgumentException("There is no matching TupleStatus for this String.");
}
private TupleStatus(String status) {
this.status = status;
}
public boolean isOpen() {
return status.equals("open");
}
public String toString() {
return status;
}
}
/**
* Represents the rpid of the status packet.
* <br><br>
* Refer to <a href="http://www.ietf.org/rfc/rfc4480.txt">RFC4480</a> for details of these statuses.
* @author Patrick Siu
* @version 0.0.1
*/
public enum Rpid {
APPOINTMENT ("appointment"),
AWAY ("away"),
BREAKFAST ("breakfast"),
BUSY ("busy"),
DINNER ("dinner"),
HOLIDAY ("holiday"),
IN_TRANSIT ("in-transit"),
LOOKING_FOR_WORK ("looking-for-work"),
LUNCH ("lunch"),
MEAL ("meal"),
MEETING ("meeting"),
ON_THE_PHONE ("on-the-phone"),
OTHER ("other"),
PERFORMANCE ("performance"),
PERMANENT_ABSENCE("permanent-absence"),
PLAYING ("playing"),
PRESENTATION ("presentation"),
SHOPPING ("shopping"),
SLEEPING ("sleeping"),
SPECTATOR ("spectator"),
STEERING ("steering"),
TRAVEL ("travel"),
TV ("tv"),
UNKNOWN ("unknown"),
VACATION ("vacation"),
WORKING ("working"),
WORSHIP ("worship");
private String desc;
public static Rpid getRpid(String rpidString) throws IllegalArgumentException {
for (Rpid r : values()) {
if (r.toString().equalsIgnoreCase(rpidString)) return r;
}
throw new IllegalArgumentException("There is no matching Rpid for the String.");
}
private Rpid(String desc) {
this.desc = desc;
}
/**
* Overridden to return the string description of the constant.
*/
public String toString() {
return desc;
}
}
private TupleStatus tupleStatus;
private Rpid rpid;
private String dmNote;
private String entity;
/**
* Constructor.
*/
public SimplePresence() {
this.tupleStatus = TupleStatus.OPEN;
this.rpid = Rpid.UNKNOWN;
this.dmNote = "";
this.entity = "";
}
public SimplePresence(TupleStatus tupleStatus) {
this.tupleStatus = tupleStatus;
this.rpid = Rpid.UNKNOWN;
this.dmNote = "";
this.entity = "";
}
public void setRpid(Rpid rpid) {
this.rpid = rpid;
}
public void setDmNote(String dmNote) {
this.dmNote = dmNote;
}
public void setEntity(String entity) {
this.entity = entity;
}
public void setTupleStatus(TupleStatus tupleStatus) {
this.tupleStatus = tupleStatus;
}
public Rpid getRpid() {
return this.rpid;
}
public String getDmNote() {
return this.dmNote;
}
public TupleStatus getTupleStatus() {
return this.tupleStatus;
}
public String toXML() {
String result =
"<?xml version='1.0' encoding='UTF-8'?>" +
"<presence xmlns='urn:ietf:params:xml:ns:pidf'" +
" xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model'" +
" xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid'" +
" xmlns:c='urn:ietf:params:xml:ns:pidf:cipid'" +
" entity='" + entity + "'>" +
"<tuple id='t" + hashCode() + "'><status><basic>" + tupleStatus.toString() + "</basic></status></tuple>" +
"<dm:person id='p" + hashCode() + "'><rpid:activities><rpid:" + rpid.toString() + "/></rpid:activities></dm:person></presence>";
// DocumentFactory docFactory = DocumentFactory.getInstance();
//
// Document xmlDocument = docFactory.createDocument();
// Element rootElement = docFactory.createDocument().addElement("presence");
//
// rootElement.addAttribute("xmlns", "urn:ietf:params:xml:ns:pidf");
// rootElement.addAttribute(new QName("xmlns", "dm"), "urn:ietf:params:xml:ns:pidf:data-model");
// rootElement.addAttribute(new QName("xmlns", "rpid"), "urn:ietf:params:xml:ns:pidf:rpid");
// rootElement.addAttribute(new QName("xmlns", "c"), "urn:ietf:params:xml:ns:pidf:cipid");
// rootElement.addAttribute("entity", entity);
//
// Element tupleElement = rootElement.addElement("tuple");
// tupleElement.addAttribute("id", "t" + Integer.toHexString(this.hashCode()));
// tupleElement.addElement("status").addElement("basic").setText(this.tupleStatus.toString());
//
// Element personElement = rootElement.addElement(new QName("dm", "person"));
// personElement.addAttribute("id", "p" + Integer.toHexString(this.hashCode()));
// personElement.addElement(new QName("rpid", "activities")).addElement("rpid:" + this.rpid.toString());
//
// if (this.dmNote != null && !this.dmNote.trim().equals("")) {
// personElement.addElement("dm:note").setText(this.dmNote);
// }
//
// return xmlDocument.asXML();
return result;
}
// public Presence convertSIPPresenceToXMPP(String sipPresence) {
// Presence xmppPresence = new Presence();
//
// SAXParser saxParser;
// try {
// SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
// saxParser = saxParserFactory.newSAXParser();
//
// } catch (Exception e) {
// Log.debug("Unable to load parser to parse SIP presence to XMPP Presence.", e);
// return xmppPresence;
// }
//
// return xmppPresence;
// }
// public String convertXMPPPresenceToSIP(Presence xmppPresence) {
// String sipPresence = "";
// String basic = "open";
// String rpid = "unknown";
// String dmNote = "";
//
// if (!xmppPresence.isAvailable()) {
// // Prepare "closed" basic presence.
// basic = "closed";
// } else {
// Presence.Show xmppPresenceShow = xmppPresence.getShow();
// if (xmppPresenceShow.equals(Presence.Show.away)) {
// rpid = "away";
// } else if (xmppPresenceShow.equals(Presence.Show.chat)) {
// rpid = "away";
// } else if (xmppPresenceShow.equals(Presence.Show.dnd)) {
// rpid = "busy";
// } else if (xmppPresenceShow.equals(Presence.Show.xa)) {
// rpid = "away";
// } else {
// rpid = "";
// }
// }
//
// sipPresence = "<?xml version='1.0' encoding='UTF-8'?>"
// + "<presence xmlns='urn:ietf:params:xml:ns:pidf' xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model' "
// + "xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid' xmlns:c='urn:ietf:params:xml:ns:pidf:cipid' "
// + "entity='pres:sip:sipdemo1@192.168.1.199'>"
// + "<tuple><status><basic>" + basic + "</basic></status></tuple>"
// + "<dm:person id='p3e32d940'><rpid:activities><rpid:" + rpid + "/></rpid:activities></dm:person></presence>";
//
// return sipPresence;
// }
public void parse(String simplePresenceXml) throws Exception {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
ByteArrayInputStream bais = new ByteArrayInputStream(simplePresenceXml.getBytes());
saxParser.parse(bais, new SimplePresenceParser());
bais.close();
}
public static SimplePresence parseSimplePresence(String simplePresenceXml) throws Exception {
SimplePresence simplePresenceObject = new SimplePresence();
simplePresenceObject.parse(simplePresenceXml);
return simplePresenceObject;
}
class SimplePresenceParser extends DefaultHandler {
private boolean isStartTag = false;
private boolean isPresence = false;
private boolean isStatus = false;
private boolean isStatusType = false;
private boolean isStatusName = false;
String elementName = null;
String paramName = null;
String userName = null;
String statusType = null;
String statusName = null;
public SimplePresenceParser() {
}
public void startElement(String namespaceURI, String sName, String qName, Attributes attrs) throws SAXException {
isStartTag = true;
elementName = (!sName.equals(""))? sName : qName;
if(elementName.equals("presence")) {
isPresence = true;
if (attrs.getIndex("entity") >= 0) {
entity = attrs.getValue("entity");
}
}
else if(elementName.equals("basic")) {
isStatus = true;
}
else if(elementName.equals("rpid:user-input")) {
isStatusType = true;
}
else if(elementName.startsWith("rpid:")) {
try {
String temp = elementName.substring(elementName.indexOf("rpid:") + 5);
if(!temp.equals("activities")) {
try {
rpid = Rpid.getRpid(temp);
}
catch (IllegalArgumentException ex) {
Log.debug(ex);
// Ignore the exception. Leave it as "unknown".
}
}
}
catch (Exception ex) {
Log.debug(ex);
}
}
else if(elementName.equals("dm:note")) {
isStatusName = true;
}
if (isPresence) {
// for(int i = 0; i < attrs.getLength(); i++) {
// if(attrs.getQName(i).equals("entity")) {
// userName = attrs.getValue(i).substring(attrs.getValue(i).indexOf("sip:"));
// }
// }
}
}
public void characters(char buf[], int offset, int len) throws SAXException {
String data = new String(buf, offset, len);
if (isStatus) {
try {
tupleStatus = TupleStatus.getTupleStatus(data);
}
catch (IllegalArgumentException ex) {
}
// if(data.equals("open")) {
// statusType = "online";
// statusName = "Online";
// }
// else {
// statusType = "offline";
// statusName = "Offline";
// }
}
else if (isStatusType) {
// statusType = data;
}
else if (isStatusName) {
dmNote = data;
// if (rpid.compareTo(Rpid.UNKNOWN) == 0) {
// try {
// rpid = Rpid.getRpid(data);
// }
// catch (IllegalArgumentException ex) {
// // Ignore the exception. Leave it as "unknown".
// }
// }
// statusName = data;
}
}
public void endElement(String namespaceURI, String sName, String qName) throws SAXException {
isStartTag = false;
elementName = (!sName.equals(""))? sName : qName;
if(elementName.equals("presence")) {
isPresence = false;
}
else if(elementName.equals("basic")) {
isStatus = false;
}
else if(elementName.equals("rpid:user-input")) {
isStatusType = false;
}
else if(elementName.equals("dm:note")) {
isStatusName = false;
}
}
public void endDocument() throws SAXException {
// obj.setUser(userName);
// obj.setType(statusType);
// obj.setStatus(statusName);
}
}
}
package org.jivesoftware.wildfire.gateway.protocols.simple;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Properties;
import java.util.TooManyListenersException;
import javax.sip.ClientTransaction;
import javax.sip.ListeningPoint;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.gateway.*;
import org.jivesoftware.wildfire.roster.*;
import org.jivesoftware.wildfire.user.User;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
/**
* A gateway session to a SIMPLE IM server.
* @author Patrick Siu
* @version 0.0.1
*/
public class SimpleSession extends TransportSession {
private SipFactory sipFactory = null;
private String sipHost;
private int sipPort;
private String username;
private String sessionId = "";
private long seqNum;
private ListeningPoint tcp = null;
private ListeningPoint udp = null;
private SipProvider tcpSipProvider;
private SipProvider udpSipProvider;
private MessageFactory messageFactory;
private AddressFactory addressFactory;
private HeaderFactory headerFactory;
private SipStack sipStack;
private SimpleSessionListener myListener;
/**
* Constructor utilizing the lesser constructor of the super class.
* @see org.jivesoftware.wildfire.gateway.TransportSession#TransportSession(org.jivesoftware.wildfire.gateway.Registration,org.xmpp.packet.JID,org.jivesoftware.wildfire.gateway.BaseTransport)
*/
public SimpleSession(Registration registration, JID jid, BaseTransport transport) {
super(registration, jid, transport);
init();
}
/**
* Constructor utilizing the greater constructor of the super class.
* @see org.jivesoftware.wildfire.gateway.TransportSession#TransportSession(org.jivesoftware.wildfire.gateway.Registration,org.xmpp.packet.JID,org.jivesoftware.wildfire.gateway.BaseTransport,java.lang.Integer)
*/
public SimpleSession(Registration registration, JID jid, BaseTransport transport, Integer priority) {
super(registration, jid, transport, priority);
init();
}
/**
* The initialization process.
*/
private void init() {
sipHost = JiveGlobals.getProperty("plugin.gateway.sip.connecthost", "");
sipPort = ((SimpleTransport) transport).generateListenerPort();
// Initialize the SipFactory
sipFactory = SipFactory.getInstance();
sipFactory.setPathName("gov.nist");
// Initialize the SipStack for this session
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", jid.getNode());
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
try {
String localIP = InetAddress.getLocalHost().getHostAddress();
sipStack = sipFactory.createSipStack(properties);
headerFactory = sipFactory.createHeaderFactory();
addressFactory = sipFactory.createAddressFactory();
messageFactory = sipFactory.createMessageFactory();
Iterator listeningPointIterator = sipStack.getListeningPoints();
while (listeningPointIterator.hasNext()) {
ListeningPoint listeningPoint = (ListeningPoint) listeningPointIterator.next();
if (listeningPoint.getIPAddress() != null &&
listeningPoint.getIPAddress().equals(localIP) &&
// listeningPoint.getPort() == sipPort &&
listeningPoint.getTransport().equals(ListeningPoint.TCP)) {
tcp = listeningPoint;
sipPort = tcp.getPort();
}
if (listeningPoint.getIPAddress() != null &&
listeningPoint.getIPAddress().equals(localIP) &&
// listeningPoint.getPort() == sipPort &&
listeningPoint.getTransport().equals(ListeningPoint.UDP)) {
udp = listeningPoint;
sipPort = udp.getPort();
}
}
if (tcp == null) {
tcp = sipStack.createListeningPoint(localIP, sipPort, ListeningPoint.TCP);
}
if (udp == null) {
udp = sipStack.createListeningPoint(localIP, sipPort, ListeningPoint.UDP);
}
Iterator sipProviderIterator = sipStack.getSipProviders();
while (sipProviderIterator.hasNext()) {
SipProvider sipProvider = (SipProvider) sipProviderIterator.next();
if (sipProvider.getListeningPoint(ListeningPoint.TCP) != null) {
tcpSipProvider = sipProvider;
}
if (sipProvider.getListeningPoint(ListeningPoint.UDP) != null) {
udpSipProvider = sipProvider;
}
}
if (tcpSipProvider == null)
tcpSipProvider = sipStack.createSipProvider(tcp);
if (udpSipProvider == null)
udpSipProvider = sipStack.createSipProvider(udp);
} catch (Exception ex) {
Log.debug(ex);
}
try {
myListener = new SimpleSessionListener(this);
tcpSipProvider.addSipListener(myListener);
udpSipProvider.addSipListener(myListener);
} catch (TooManyListenersException ex) {
Log.debug(ex);
}
try {
sipStack.start();
} catch (SipException ex) {
Log.debug(ex);
}
seqNum = 1L;
}
/**
* Perform rollback action once the login fails or logout goes on the way.
*/
private void rollback() {
}
public void updateStatus(PresenceType presenceType, String verboseStatus) {
Log.debug("SimpleSession(" + getJID().getNode() + ").updateStatus: Method commenced!");
}
public void addContact(RosterItem item) {
String nickname = getTransport().convertJIDToID(item.getJid());
if (item.getNickname() != null && !item.getNickname().equals("")) {
nickname = item.getNickname();
}
lockRoster(item.getJid().toString());
JID destJid = item.getJid();
String destId = ((SimpleTransport) transport).convertJIDToID(destJid);
Log.debug("SimpleSession(" + this.jid.getNode() + ").addContact: Starting addContact function for " + destId);
List<Header> customHeaders = new ArrayList<Header>(13);
try { customHeaders.add(headerFactory.createExpiresHeader(365 * 24 * 60 * 60)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.ACK)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.BYE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.CANCEL)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.INFO)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.INVITE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.MESSAGE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.NOTIFY)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.OPTIONS)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.REFER)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.SUBSCRIBE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createEventHeader("presence")); }
catch (Exception e) {} // Ignore
prepareRequest(RequestType.SUBSCRIBE, destId, null, null, 1L, 70, customHeaders, null);
destJid = getTransport().convertIDToJID(destId);
try {
Log.debug("SimpleSession(" + getJID().getNode() + ").addContact: Adding contact '" + destJid.toString() + "' to roster...");
getTransport().addOrUpdateRosterItem(getJID(), destJid, nickname, item.getGroups());
Log.debug("SimpleSession(" + getJID().getNode() + ").addContact: Contact '" + destJid.toString() + "' added!");
}
catch (Exception ex) {
Log.debug("SimpleSession(" + getJID().getNode() + ").addContact: Unable to add contact.", ex);
}
}
public void removeContact(RosterItem item) {
}
public void updateContact(RosterItem item) {
}
public void sendMessage(JID jid, String message) {
Log.debug("SimpleSession(" + this.jid.getNode() + "): Starting message sending process.");
ContentTypeHeader contentTypeHeader = null;
try {
contentTypeHeader = headerFactory.createContentTypeHeader("text", "plain");
}
catch (Exception e) {
Log.debug("SimpleSession(" + this.jid.getNode() + ").sendMessage: Unable to initiate ContentType header.", e);
return;
}
Log.debug("SimpleSession(" + this.jid.getNode() + "): Finished adding ContentType header.");
MessageContent content = new MessageContent(contentTypeHeader, message);
if (!prepareRequest(RequestType.MESSAGE, ((SimpleTransport) transport).convertJIDToID(jid), null, null, 1L, 70, null, content)) {
Log.debug("SimpleSession(" + this.jid.getNode() + ").sendMessage: Unable to send message!");
}
}
public void sendServerMessage(String message) {
}
public void sendChatState(JID jid, ChatStateType chatState) {
}
public void retrieveContactStatus(JID jid) {
}
public void resendContactStatuses(JID jid) {
}
// The following are SimpleSession specific methods
public void login(PresenceType presenceType, String verboseStatus) {
if (!this.isLoggedIn()) {
this.setLoginStatus(TransportLoginStatus.LOGGING_IN);
Log.debug("SimpleSession(" + getJID().getNode() + ").login: Start login as " + registration.getUsername() + ".");
List<Header> customHeaders = new ArrayList<Header>(13);
try { customHeaders.add(headerFactory.createExpiresHeader(365 * 24 * 60 * 60)); }
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").login: " +
"Unable to set the expiry interval, which is essential for a login.", e);
return;
}
try { customHeaders.add(headerFactory.createAllowHeader(Request.ACK)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.BYE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.CANCEL)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.INFO)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.INVITE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.MESSAGE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.NOTIFY)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.OPTIONS)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.REFER)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createAllowHeader(Request.SUBSCRIBE)); }
catch (Exception e) {} // Ignore
try { customHeaders.add(headerFactory.createEventHeader("presence")); }
catch (Exception e) {} // Ignore
String myUsername = registration.getUsername();
if (myUsername.indexOf("sip:") < 0) myUsername = "sip:" + myUsername;
if (myUsername.indexOf("@") < 0) myUsername = myUsername + "@" + sipHost;
String callId = null;
try {
callId = udpSipProvider.getNewCallId().getCallId();
this.sessionId = callId;
}
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").login: Unable to create a SIP session ID!!", e);
this.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
return;
}
Log.debug("SimpleSession(" + getJID().getNode() + ").login: Created Session ID = '" + this.sessionId + "'!!");
if (!prepareRequest(RequestType.REGISTER, myUsername, null, this.sessionId, seqNum++, 70, customHeaders, null)) {
this.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
}
}
}
public void logout() {
this.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
// Lots of logout work here...
Log.debug("SimpleSession(" + getJID().getNode() + ").logout: Preparing logout packet...");
List<Header> customHeaders = new ArrayList<Header>(1);
try { customHeaders.add(headerFactory.createExpiresHeader(0)); }
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").logout: " +
"Unable to set the expiry interval, which is essential for a logout.", e);
return;
} // Ignore
String myUsername = registration.getUsername();
if (myUsername.indexOf("sip:") < 0) myUsername = "sip:" + myUsername;
if (myUsername.indexOf("@") < 0) myUsername = myUsername + "@" + sipHost;
prepareRequest(RequestType.REGISTER, myUsername, null, this.sessionId, seqNum++, 70, customHeaders, null);
// this.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
}
public void removeStack() {
Log.debug("SimpleSession for " + jid.getNode() + " is going to shut down!");
tcpSipProvider.removeSipListener(myListener);
udpSipProvider.removeSipListener(myListener);
myListener = null;
Log.debug("SimpleSession for " + jid.getNode() + " has their listeners removed.");
try {
sipStack.deleteSipProvider(tcpSipProvider);
sipStack.deleteSipProvider(udpSipProvider);
sipStack.deleteListeningPoint(tcp);
sipStack.deleteListeningPoint(udp);
}
catch (Exception ex) {
Log.debug(ex);
Log.debug("SimpleSession for " + jid.getNode() + " is unable to gracefully shut down.");
}
sipStack.stop();
sipStack = null;
}
public void finalize() {
Log.debug("SimpleSession for " + jid.getNode() + ": Finalize function initialized!");
if (this.getLoginStatus().equals(TransportLoginStatus.LOGGED_IN)) {
logout();
}
}
///// Simple specific functions
/**
* An inner enum encapsulating SIP Request types.
*/
private enum RequestType {
ACK (Request.ACK),
BYE (Request.BYE),
CANCEL (Request.CANCEL),
INFO (Request.INFO),
INVITE (Request.INVITE),
MESSAGE (Request.MESSAGE),
NOTIFY (Request.NOTIFY),
OPTIONS (Request.OPTIONS),
PRACK (Request.PRACK),
PUBLISH (Request.PUBLISH),
REFER (Request.REFER),
REGISTER (Request.REGISTER),
SUBSCRIBE(Request.SUBSCRIBE),
UPDATE (Request.UPDATE);
private String sipReqType;
RequestType(String sipReqType) {
this.sipReqType = sipReqType;
}
public String toString() {
return sipReqType;
}
}
/**
* An inner class representing the content of a SIP message.
*/
private class MessageContent {
private ContentTypeHeader contentTypeHeader;
private String content;
MessageContent(ContentTypeHeader contentTypeHeader, String content) {
this.contentTypeHeader = contentTypeHeader;
this.content = content;
}
public ContentTypeHeader getContentTypeHeader() {
return this.contentTypeHeader;
}
public String getContent() {
return this.content;
}
}
/**
* Prepares a Request packet.
* <br><br>
* The "From", "To", "Via", "Contact", "CSeq", "MaxForwards" and "CallId" headers,
* as well as the content (if provided) are prepared in the method.
* <br>
* Additional headers should be provided as customer headers. See the "headers" parameter for further details.
* @param requestType An inner request type enum
* @param destination The recipient of this request
* @param toTag Additional tag code of the destination. Can usually leave it <code>null</code>.
* @param callId A String representing an ongoing SIP CallID. Leave it <code>null</code> if a new CallID should be generated.
* @param seqNum A sequence number for an ongoing session.
* @param maxForward Maximum times of forwarding allowed for this packet.
* @param headers Additional headers that have to be added. Leave <code>null</code> if no custom header is to be added.
* @param content An object containing the content of the message, as well as the header defining the content type.
* Can leave <code>null</code> if no content is to be specified.
* @see org.jivesoftware.wildfire.gateway.protocols.simple.SimpleSession.RequestType
*/
private boolean prepareRequest(
RequestType requestType,
String destination,
String toTag,
String callId,
long seqNum,
int maxForward,
List<Header> headers,
MessageContent content) {
String myJiveId = this.jid.getNode();
String mySipUsername = registration.getUsername();
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing request packet of type '" + requestType + "'");
// Prepare "From" header
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing \"From\" header...");
FromHeader fromHeader = null;
try {
SipURI fromUri = addressFactory.createSipURI(mySipUsername, sipHost);
Address fromNameAddress = addressFactory.createAddress(fromUri);
fromNameAddress.setDisplayName(mySipUsername);
fromHeader = headerFactory.createFromHeader(fromNameAddress, "SipGateway");
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing FromHeader.", e);
return false;
}
// Prepare "To" header
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing \"To\" header...");
ToHeader toHeader = null;
String destUsername = "";
String destAddress = "";
if (destination.indexOf(":") > 0 && destination.indexOf("@") > destination.indexOf(":")) {
destUsername = destination.substring(destination.indexOf(":") + 1, destination.indexOf("@"));
destAddress = destination.substring(destination.indexOf("@") + 1);
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: destUsername = '" + destUsername + "'; destAddress = '" + destAddress + "'");
}
else {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing ToHeader.",
new IllegalArgumentException("The destination specified is not a valid SIP address"));
return false;
}
try {
SipURI toAddress = addressFactory.createSipURI(destUsername, destAddress);
Address toNameAddress = addressFactory.createAddress(toAddress);
String displayName = destUsername;
try {
RosterItem ri = getRoster().getRosterItem(this.getTransport().convertIDToJID(destination));
if (ri != null) displayName = ri.getNickname();
}
catch (Exception e) {} // Ignore the exception. We don't need to handle it.
toNameAddress.setDisplayName(displayName);
toHeader = headerFactory.createToHeader(toNameAddress, toTag);
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing ToHeader.", e);
return false;
}
// Prepare "Via" header
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing \"Via\" header...");
ArrayList viaHeaders = new ArrayList();
try {
ViaHeader viaHeader = headerFactory.createViaHeader(InetAddress.getLocalHost().getHostAddress(), sipPort, ListeningPoint.UDP, null);
viaHeaders.add(viaHeader);
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing ViaHeader.", e);
return false;
}
// Prepare "CallId" header
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing \"CallId\" header...");
CallIdHeader callIdHeader = null;
try {
if (callId != null)
callIdHeader = headerFactory.createCallIdHeader(callId);
else
callIdHeader = udpSipProvider.getNewCallId();
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing CallIdHeader.", e);
return false;
}
// Prepare "CSeq" header
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing \"CSeq\" header...");
CSeqHeader cSeqHeader = null;
try {
cSeqHeader = headerFactory.createCSeqHeader(seqNum, requestType.toString());
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing CSeqHeader.", e);
return false;
}
// Prepare "MaxForwards" header
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing \"MaxForwards\" header...");
MaxForwardsHeader maxForwardsHeader = null;
try {
maxForwardsHeader = headerFactory.createMaxForwardsHeader(maxForward);
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing MaxForwardsHeader.", e);
return false;
}
// Prepare request URI
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing request URI...");
SipURI requestURI = null;
try {
requestURI = addressFactory.createSipURI(destUsername, destAddress);
requestURI.setTransportParam(ListeningPoint.UDP);
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when preparing Request URI.", e);
return false;
}
// Instantiate Request packet
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Instantiating Request packet...");
Request request = null;
try {
request = messageFactory.createRequest(
requestURI, requestType.toString(),
callIdHeader, cSeqHeader,
fromHeader, toHeader,
viaHeaders, maxForwardsHeader
);
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when instantiating Request packet.", e);
return false;
}
// Add custom headers
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Start adding custom headers...");
int headerCount = 0;
if (headers != null) {
headerCount = headers.size();
for (ListIterator<Header> headersIterator = headers.listIterator(); headersIterator.hasNext(); ) {
Header aHeader = headersIterator.next();
try {
request.addHeader(aHeader);
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when adding a " +
aHeader.getClass().toString() + " to the request packet.", e);
headerCount--;
}
}
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Finished adding custom headers. " +
headerCount + " of " + headers.size() + " headers successfully added.");
}
else {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: The custom headers input is null. No custom headers to add.");
}
// Add "Contact" header
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Preparing \"Contact\" header...");
try {
SipURI contactURI;
if (requestType.equals(RequestType.NOTIFY))
contactURI = addressFactory.createSipURI(null, InetAddress.getLocalHost().getHostAddress());
else
contactURI = addressFactory.createSipURI(mySipUsername, InetAddress.getLocalHost().getHostAddress());
contactURI.setPort(sipPort);
// Address contactAddress = addressFactory.createAddress("<" + InetAddress.getLocalHost().getHostAddress() + ":" + sipPort + ">");
Address contactAddress = addressFactory.createAddress(contactURI);
if (!requestType.equals(RequestType.NOTIFY))
contactAddress.setDisplayName(mySipUsername);
ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
request.addHeader(contactHeader);
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when adding ContactHeader.", e);
return false;
}
if (content != null) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Content is specified. Adding content...");
try {
request.setContent(content.getContent(), content.getContentTypeHeader());
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when adding content to the request packet.", e);
// Just tell, then continue the request!
}
}
// Send the request
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Sending Request packet: \n" + request.toString());
try {
// udpSipProvider.sendRequest(request);
ClientTransaction clientTransaction = udpSipProvider.getNewClientTransaction(request);
clientTransaction.sendRequest();
}
catch (Exception e) {
Log.debug("SimpleSession(" + myJiveId + ").prepareRequest: Exception occured when sending Request packet.", e);
return false;
}
return true;
}
public void contactSubscribed(String targetSipAddress) {
try {
Roster roster = getTransport().getRosterManager().getRoster(getJID().getNode());
JID contactJID = getTransport().convertIDToJID(targetSipAddress);
RosterItem item = roster.getRosterItem(contactJID);
Log.debug("SimpleSession(" + getJID().getNode() + ").contactSubscribed: Preparing presence packet...");
Presence presence = new Presence();
presence.setFrom(contactJID);
presence.setTo(getJID());
presence.setType(Presence.Type.subscribed);
getTransport().sendPacket(presence);
Log.debug("SimpleSession(" + getJID().getNode() + ").contactSubscribed: Presence packet sent ==> \n" + presence.toXML());
// syncContactGroups(contact, item.getGroups());
unlockRoster(contactJID.toString());
}
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").contactSubscribed: Exception occured when adding pending contact " + targetSipAddress, e);
JID contactJID = getTransport().convertIDToJID(targetSipAddress);
unlockRoster(contactJID.toString());
}
}
public void sendResponse(int status, Request request) {
try {
Log.debug("SimpleSession for " + this.jid.getNode() + ": Starting response sending process.");
Response response = messageFactory.createResponse(status, request);
udpSipProvider.sendResponse(response);
Log.debug("SimpleSession for " + this.jid.getNode() + ": Response sent!");
}
catch (Exception ex) {
Log.debug("SimpleSession for " + this.jid.getNode() + ": ", ex);
}
}
/**
* Sends a NOTIFY packet based on the SUBSCRIBE packet received.
* @throw
*/
public void sendNotify(Request inputRequest) throws Exception {
if (!inputRequest.getMethod().equals(Request.SUBSCRIBE)) {
// Should throw an Exception telling the packet is wrong;
throw new Exception("The REQUEST packet is not of method SUBSCRIBE!");
}
String dest = "";
String toTag = "";
if (inputRequest.getHeader(FromHeader.NAME) != null) {
FromHeader fromHeader = (FromHeader) inputRequest.getHeader(FromHeader.NAME);
toTag = fromHeader.getTag();
dest = fromHeader.getAddress().getURI().toString();
}
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Parsing SUBSCRIBE packet...");
long seqNum = 1L;
if (inputRequest.getHeader(CSeqHeader.NAME) != null) {
seqNum = ((CSeqHeader) inputRequest.getHeader(CSeqHeader.NAME)).getSeqNumber() + 1;
}
int expires = 0;
if (inputRequest.getHeader(ExpiresHeader.NAME) != null) {
expires = ((ExpiresHeader) inputRequest.getHeader(ExpiresHeader.NAME)).getExpires();
}
String callId = null;
if (inputRequest.getHeader(CallIdHeader.NAME) != null) {
callId = ((CallIdHeader) inputRequest.getHeader(CallIdHeader.NAME)).getCallId();
}
User me = XMPPServer.getInstance().getUserManager().getUser(getJID().getNode());
Presence myPresence = XMPPServer.getInstance().getPresenceManager().getPresence(me);
List<Header> routeHeaders = new ArrayList<Header>();
String routingProxies = "";
for (Iterator recRouteHeaders = inputRequest.getHeaders(RecordRouteHeader.NAME); recRouteHeaders.hasNext(); )
routingProxies += "," + ((RecordRouteHeader) recRouteHeaders.next()).toString().substring("Record-Route: ".length());
if (routingProxies.startsWith(",")) routingProxies = routingProxies.substring(1);
int commaIndex = routingProxies.lastIndexOf(",");
while (true) {
String uri = "";
if (commaIndex > 0)
uri = routingProxies.substring(commaIndex + 1);
else
uri = routingProxies;
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: uri = " + uri);
// Works and works here...
if (uri != null && uri.trim().length() > 0) {
RouteHeader routeHeader = headerFactory.createRouteHeader(addressFactory.createAddress(uri));
routeHeaders.add(routeHeader);
}
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: routeHeaders.size = " +
routeHeaders.size());
if (commaIndex < 0) break;
routingProxies = routingProxies.substring(0, commaIndex);
commaIndex = routingProxies.lastIndexOf(",");
}
sendNotify(dest, toTag, callId, seqNum, expires, 70, myPresence, routeHeaders);
}
public void sendNotify(String dest, String toTag, String callId, long seqNum, int expires, int maxForward, Presence presence, List<Header> routeHeaders) {
List<Header> customHeaders = new ArrayList<Header>(3);
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Setting subscription state header...");
try {
SubscriptionStateHeader subscriptionStateHeader = headerFactory.createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE.toLowerCase());
subscriptionStateHeader.setExpires(expires);
customHeaders.add(subscriptionStateHeader);
}
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Unable to set subscription state header.", e);
return;
}
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Setting event header...");
try {
customHeaders.add(headerFactory.createEventHeader("presence"));
}
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Unable to set event header.", e);
return;
}
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Adding route headers...");
try {
customHeaders.addAll(routeHeaders);
}
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Unable to add route headers.", e);
return;
}
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Writing simple presence.");
String presenceContent = "";
try {
SimplePresence simplePresence = new SimplePresence();
simplePresence.setEntity("pres:" + registration.getUsername() + "@" + sipHost);
simplePresence.setDmNote(presence.getStatus());
if (presence.getStatus() != null && presence.getStatus().equalsIgnoreCase("Offline"))
simplePresence.setTupleStatus(SimplePresence.TupleStatus.CLOSED);
else {
simplePresence.setTupleStatus(SimplePresence.TupleStatus.OPEN);
if (presence.getShow() != null) {
switch (presence.getShow()) {
case away:
simplePresence.setRpid(SimplePresence.Rpid.AWAY);
break;
case dnd:
simplePresence.setRpid(SimplePresence.Rpid.BUSY);
break;
case xa:
simplePresence.setRpid(SimplePresence.Rpid.AWAY);
break;
default:
break;
}
}
}
presenceContent =simplePresence.toXML();
}
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Unable to write simple presence.", e);
return;
}
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Creating content type header.");
ContentTypeHeader contentTypeHeader;
try {
contentTypeHeader = headerFactory.createContentTypeHeader("application", "pidf+xml");
}
catch (Exception e) {
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Unable to create content type header.", e);
return;
}
Log.debug(presenceContent);
MessageContent msgContent = new MessageContent(contentTypeHeader, presenceContent);
if (!prepareRequest(RequestType.NOTIFY, dest, toTag, callId, seqNum, maxForward, customHeaders, msgContent)) {
Log.debug("SimpleSession(" + getJID().getNode() + ").sendNotify: Unable to send NOTIFY packet.");
}
}
}
\ No newline at end of file
package org.jivesoftware.wildfire.gateway.protocols.simple;
import java.util.Date;
import java.util.ListIterator;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.SipListener;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.address.Address;
import javax.sip.address.URI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.RecordRouteHeader;
import javax.sip.header.SubscriptionStateHeader;
import javax.sip.header.ToHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.TransportLoginStatus;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
/**
* A listener for a SIMPLE session.
* <br><br>
* Instances of this class serve as an assistant to SimpleSession objects,
* carrying out works of receiving messages or responses from the SIP server
* or another remote client.
*
* @author Patrick Siu
* @version 0.0.1
*/
public class SimpleSessionListener implements SipListener {
/**
* Stores the SIMPLE session object to which this listener belongs.
*/
private SimpleSession mySimpleSession;
/**
* Stores the Jive username using this SIMPLE session listener.
* <br><br>
* The storage is for logging purpose.
*/
private String myUsername;
/**
* Constructor.
* @param mySimpleSession The SIMPLE session object to which this listener belongs.
*/
public SimpleSessionListener(SimpleSession mySimpleSession) {
this.mySimpleSession = mySimpleSession;
this.myUsername = mySimpleSession.getJID().getNode();
}
public void processRequest(RequestEvent requestEvent) {
int responseCode = 200;
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: Received a request event: \n" + requestEvent.getRequest().toString());
String fromAddr = "";
Request request = requestEvent.getRequest();
ListIterator headerNames = request.getHeaderNames();
while (headerNames.hasNext()) {
String headerName = (String) headerNames.next();
if (headerName.equals(FromHeader.NAME)) {
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
Address fromAddress = fromHeader.getAddress();
String displayName = fromAddress.getDisplayName();
URI fromUri = fromAddress.getURI();
if (fromUri != null) {
fromAddr = fromUri.toString();
break;
}
}
}
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: Request method = '" + request.getMethod() + "'");
if (request.getMethod().equals(Request.MESSAGE)) {
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: Starting MESSAGE request handling process.");
JID senderJid = mySimpleSession.getTransport().convertIDToJID(fromAddr);
String msgContent = new String((byte []) request.getContent());
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: Forwarding MESSAGE request as XMPP message, setting from = " +
senderJid + " and content = '" + msgContent + "'");
mySimpleSession.getTransport().sendMessage(mySimpleSession.getJID(), senderJid, msgContent);
mySimpleSession.sendResponse(responseCode, request);
}
else if (request.getMethod().equals(Request.NOTIFY)) {
SubscriptionStateHeader subscriptionStateHeader = (SubscriptionStateHeader) request.getHeader(SubscriptionStateHeader.NAME);
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: NOTIFY request handling process started.");
if (subscriptionStateHeader.getState().equalsIgnoreCase(SubscriptionStateHeader.ACTIVE)) {
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: NOTIFY Active!");
int expires = subscriptionStateHeader.getExpires();
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: NOTIFY Expiry = " + expires);
try {
Presence presence = new Presence();
presence.setFrom(mySimpleSession.getTransport().convertIDToJID(fromAddr));
presence.setTo(mySimpleSession.getJID());
if (expires > 0) {
String content = "";
if (request.getContent() != null)
content = new String((byte []) request.getContent());
if (content.length() > 0) {
SimplePresence simplePresence = SimplePresence.parseSimplePresence(content);
if (simplePresence.getTupleStatus().isOpen()) {
presence.setStatus("Online");
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: " +
"SIP user '" + fromAddr + "' is '" + simplePresence.getRpid().toString() + "'!");
switch (simplePresence.getRpid()) {
case AWAY:
presence.setShow(Presence.Show.away);
presence.setStatus("Away");
break;
case BUSY:
presence.setShow(Presence.Show.dnd);
presence.setStatus("Do Not Disturb");
break;
case HOLIDAY:
presence.setShow(Presence.Show.xa);
presence.setStatus("(SIP) On Holiday");
break;
case IN_TRANSIT:
presence.setShow(Presence.Show.xa);
presence.setStatus("(SIP) In Transit");
break;
case ON_THE_PHONE:
presence.setShow(Presence.Show.away);
presence.setStatus("On Phone");
break;
case PERMANENT_ABSENCE:
presence.setStatus("Offline");
break;
case SLEEPING:
presence.setShow(Presence.Show.away);
presence.setStatus("(SIP) Idle");
break;
default:
break;
}
}
} else {
presence.setStatus("Offline");
}
} else {
presence.setType(Presence.Type.unsubscribed);
}
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: Sending XMPP presence packet.");
mySimpleSession.getTransport().sendPacket(presence);
} catch (Exception ex) {
Log.debug("SimpleSessionListener(" + myUsername + ").processRequest: Exception occured when processing NOTIFY packet...", ex);
}
}
mySimpleSession.sendResponse(responseCode, request);
}
else if (request.getMethod().equals(Request.SUBSCRIBE)) {
Log.debug("SimpleSessionListener for " + myUsername + ": SUBSCRIBE request handling process.");
mySimpleSession.sendResponse(202, request);
Log.debug("SimpleSessionListener for " + myUsername + ": SUBSCRIBE should be followed by a NOTIFY");
// Send NOTIFY packet.
try {
mySimpleSession.sendNotify(request);
}
catch (Exception e) {
Log.debug("SimpleSessionListener for " + myUsername + ": Unable to prepare NOTIFY packet.", e);
}
// long seqNum = 1L;
// if (request.getHeader(CSeqHeader.NAME) != null) {
// seqNum = ((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber() + 1;
// }
//
// int expires = 0;
// if (request.getHeader(ExpiresHeader.NAME) != null) {
// expires = ((ExpiresHeader) request.getHeader(ExpiresHeader.NAME)).getExpires();
// }
//
// String callId = null;
// if (request.getHeader(CallIdHeader.NAME) != null) {
// callId = ((CallIdHeader) request.getHeader(CallIdHeader.NAME)).getCallId();
// }
// int maxForward = 0;
// if (request.getHeader(MaxForwardsHeader.NAME) != null) {
// maxForward = ((MaxForwardsHeader) request.getHeader(MaxForwardsHeader.NAME)).getMaxForwards();
// }
// if (maxForward > 0) maxForward--;
// if (request.getHeader(RecordRouteHeader.NAME) != null) {
// String recordRouteHeader = ((RecordRouteHeader) request.getHeader(RecordRouteHeader.NAME)).toString();
// }
// Send notify packet to show my own presence.
// mySimpleSession.sendNotify(fromAddr, callId, seqNum, expires, maxForward, new Presence());
}
}
public void processResponse(ResponseEvent responseEvent) {
Log.debug("SimpleSessionListener for " + myUsername + ": Received a response event: " + responseEvent.getResponse().toString());
String fromAddr = "";
String toAddr = "";
Response response = responseEvent.getResponse();
if (response.getHeader(FromHeader.NAME) != null) {
FromHeader fromHeader = (FromHeader) response.getHeader(FromHeader.NAME);
fromAddr = fromHeader.getAddress().getURI().toString();
}
if (response.getHeader(ToHeader.NAME) != null) {
ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
toAddr = toHeader.getAddress().getURI().toString();
}
if (response.getHeader(CSeqHeader.NAME) != null) {
String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME)).getMethod();
if (method.equals(Request.REGISTER)) {
if (response.getStatusCode() - response.getStatusCode() % 100 == 200) {
int expires = 0;
if (response.getHeader(ContactHeader.NAME) != null) {
expires = ((ContactHeader) response.getHeader(ContactHeader.NAME)).getExpires();
} else if (response.getHeader(ExpiresHeader.NAME) != null) {
expires = ((ExpiresHeader) response.getHeader(ExpiresHeader.NAME)).getExpires();
}
if (expires > 0) {
Log.debug("SimpleSessionListener(" + myUsername + ").processResponse: " +
mySimpleSession.getRegistration().getUsername() + " log in successful!");
mySimpleSession.getRegistration().setLastLogin(new Date());
mySimpleSession.setLoginStatus(TransportLoginStatus.LOGGED_IN);
}
else {
if (mySimpleSession.getLoginStatus().equals(TransportLoginStatus.LOGGING_OUT)) {
Log.debug("SimpleSessionListener(" + myUsername + ").processResponse: " +
mySimpleSession.getRegistration().getUsername() + " log out successful!");
mySimpleSession.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
mySimpleSession.removeStack();
}
}
}
}
if (method.equals(Request.SUBSCRIBE)) {
if (response.getStatusCode() - response.getStatusCode() % 100 == 200) {
Log.debug("SimpleSessionListener for " + myUsername + ": Handling SUBSCRIBE acknowledgement!!");
int expires = 0;
if (response.getHeader(ContactHeader.NAME) != null) {
expires = ((ContactHeader) response.getHeader(ContactHeader.NAME)).getExpires();
}
if (response.getHeader(ExpiresHeader.NAME) != null) {
expires = ((ExpiresHeader) response.getHeader(ExpiresHeader.NAME)).getExpires();
}
// Presence presence = new Presence();
// presence.setFrom(mySimpleSession.getTransport().convertIDToJID(toAddr));
// presence.setTo(mySimpleSession.getJID());
if (expires > 0) {
// Confirm addition of roster item
// presence.setType(Presence.Type.subscribed);
mySimpleSession.contactSubscribed(toAddr);
} else {
// Confirm deletion of roster item
// presence.setType(Presence.Type.unsubscribed);
}
Log.debug("SimpleSessionListener for " + myUsername + ": Handled SUBSCRIBE acknowledgement!!");
// mySimpleSession.getTransport().sendPacket(presence);
}
}
}
}
public void processTimeout(TimeoutEvent timeoutEvent) {
Log.debug("SimpleSessionListener for " + myUsername + " received a timeout event: " +
timeoutEvent.getTimeout().toString());
}
public void processIOException(IOExceptionEvent iOExceptionEvent) {
Log.debug("SimpleSessionListener for " + myUsername + " received an IOException event: " +
iOExceptionEvent.toString());
}
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
Log.debug("SimpleSessionListener(" + myUsername + "): Received a TransactionTerminatedEvent [" + transactionTerminatedEvent.hashCode() + "]");
}
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
Log.debug("SimpleSessionListener for " + myUsername + " received a dialog terminated event: " +
dialogTerminatedEvent.getDialog().getDialogId());
}
public void finalize() {
Log.debug("SimpleSessionListener for " + myUsername + " is being shut down!!");
mySimpleSession = null;
}
}
\ No newline at end of file
package org.jivesoftware.wildfire.gateway.protocols.simple;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.TooManyListenersException;
import javax.sip.InvalidArgumentException;
import javax.sip.ListeningPoint;
import javax.sip.ObjectInUseException;
import javax.sip.PeerUnavailableException;
import javax.sip.SipFactory;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.TransportNotSupportedException;
import javax.sip.address.AddressFactory;
import javax.sip.header.HeaderFactory;
import javax.sip.message.MessageFactory;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.BaseTransport;
import org.jivesoftware.wildfire.gateway.PresenceType;
import org.jivesoftware.wildfire.gateway.Registration;
import org.jivesoftware.wildfire.gateway.TransportLoginStatus;
import org.jivesoftware.wildfire.gateway.TransportSession;
import org.xmpp.packet.JID;
/**
* A transport implementation for SIMPLE protocol.
* @author Patrick Siu
* @version 0.0.1
*/
public class SimpleTransport extends BaseTransport {
SipFactory sipFactory = null;
public SimpleTransport() {
super();
// Initialize the SipFactory
sipFactory = SipFactory.getInstance();
sipFactory.setPathName("gov.nist");
}
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new SimpleSession(registration, jid, this, priority);
// Possibly more work here!
((SimpleSession) session).login(presenceType, verboseStatus);
return session;
}
public void registrationLoggedOut(TransportSession session) {
((SimpleSession) session).logout();
session.sessionDone();
// Just in case.
// session.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
}
public String getTerminologyUsername() {
return LocaleUtils.getLocalizedString("gateway.sip.username", "gateway");
}
public String getTerminologyPassword() {
return LocaleUtils.getLocalizedString("gateway.sip.password", "gateway");
}
public String getTerminologyNickname() {
// If this string is needed, then take it. Just put a draft code to ensure integrity.
String result = null;
return result;
}
public String getTerminologyRegistration() {
return LocaleUtils.getLocalizedString("gateway.sip.registration", "gateway");
}
public Boolean isPasswordRequired() {
// Just put a draft code to ensure integrity.
Boolean result = true;
return result;
}
public Boolean isNicknameRequired() {
// Just put a draft code to ensure integrity.
Boolean result = false;
return result;
}
public Boolean isUsernameValid(String username) {
// Just put a draft code to ensure integrity.
Boolean result = username.matches("\\w+");
return result;
}
// The following code are generic custom classes for SIP-XMPP conversion.
public void convertJabStatusToSIP(PresenceType jabStatus) {
}
public void convertSIPStatusToJap() {
}
/**
* An improved method to do the trick.
*/
public String convertJIDToID(JID jid) {
String node = jid.getNode();
while (!JID.unescapeNode(node).equals(node)) {
node = JID.unescapeNode(node);
}
return node;
}
int portOffset = 0;
synchronized int generateListenerPort() {
return (ListeningPoint.PORT_5060 + (++portOffset));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.sip.connecthost" var="host" desckey="gateway.web.settings.host" default="localhost"/>
<item type="text" sysprop="plugin.gateway.sip.connectport" var="port" desckey="gateway.web.settings.port" default="5060"/>
</rightpanel>
</optionsconfig>
......@@ -31,6 +31,7 @@
trEnabled.put("irc", plugin.getTransportInstance("irc").isEnabled());
trEnabled.put("msn", plugin.getTransportInstance("msn").isEnabled());
trEnabled.put("yahoo", plugin.getTransportInstance("yahoo").isEnabled());
trEnabled.put("sip", plugin.getTransportInstance("sip").isEnabled());
String success = request.getParameter("success");
webManager.init(request, response, session, application, out);
......@@ -155,6 +156,7 @@
if (webManager.getPageProperty("gateway-registrations", "filterYAHOO", 0) != 0) { filteropts.add("yahoo"); }
if (webManager.getPageProperty("gateway-registrations", "filterIRC", 0) != 0) { filteropts.add("irc"); }
if (webManager.getPageProperty("gateway-registrations", "filterSIGNEDON", 0) != 0) { filteropts.add("signedon"); }
if (webManager.getPageProperty("gateway-registrations", "filterSIP", 0) != 0) { filteropts.add("sip"); }
}
else {
filteropts.add("aim");
......@@ -162,6 +164,7 @@
filteropts.add("msn");
filteropts.add("yahoo");
filteropts.add("irc");
filteropts.add("sip");
}
webManager.setPageProperty("gateway-registrations", "filterSET", 1);
......@@ -171,6 +174,7 @@
webManager.setPageProperty("gateway-registrations", "filterYAHOO", filteropts.contains("yahoo") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterIRC", filteropts.contains("irc") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterSIGNEDON", filteropts.contains("signedon") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterSIP", filteropts.contains("sip") ? 1 : 0);
int resCount = 0;
for (Registration registration : registrations) {
......@@ -341,6 +345,7 @@
<% if (trEnabled.get("icq")) { %> <option value="icq"><fmt:message key="gateway.icq.shortservice" /></option> <% } %>
<% if (trEnabled.get("irc")) { %> <option value="irc"><fmt:message key="gateway.irc.shortservice" /></option> <% } %>
<% if (trEnabled.get("msn")) { %> <option value="msn"><fmt:message key="gateway.msn.shortservice" /></option> <% } %>
<% if (trEnabled.get("sip")) { %> <option value="sip"><fmt:message key="gateway.sip.shortservice" /></option> <% } %>
<% if (trEnabled.get("yahoo")) { %> <option value="yahoo"><fmt:message key="gateway.yahoo.shortservice" /></option> <% } %>
</select><br>
<strong><fmt:message key="gateway.web.registrations.gateway" /></strong>
......@@ -432,28 +437,33 @@
<strong>Filter by:</strong>
<label for="filterAIMcheckbox">
<input type="checkbox" name="filter[]" value="aim" <%= ((filteropts.contains("aim")) ? "checked" : "") %> id="filterAIMcheckbox">
<img src="images/aim.gif" alt="" border="0">
<span><fmt:message key="gateway.aim.shortservice" /></span>
<img src="images/aim.gif" alt="" border="0" alt="<fmt:message key="gateway.aim.shortservice" />">
<!--<span><fmt:message key="gateway.aim.shortservice" /></span>-->
</label>
<label for="filterICQcheckbox">
<input type="checkbox" name="filter[]" value="icq" <%= ((filteropts.contains("icq")) ? "checked" : "") %> id="filterICQcheckbox">
<img src="images/icq.gif" alt="" border="0">
<span><fmt:message key="gateway.icq.shortservice" /></span>
<img src="images/icq.gif" alt="" border="0" alt="<fmt:message key="gateway.icq.shortservice" />">
<!--<span><fmt:message key="gateway.icq.shortservice" /></span>-->
</label>
<label for="filterIRCcheckbox">
<input type="checkbox" name="filter[]" value="irc" <%= ((filteropts.contains("irc")) ? "checked" : "") %> id="filterIRCcheckbox">
<img src="images/irc.gif" alt="" border="0">
<span><fmt:message key="gateway.irc.shortservice" /></span>
<img src="images/irc.gif" alt="" border="0" alt="<fmt:message key="gateway.irc.shortservice" />">
<!--<span><fmt:message key="gateway.irc.shortservice" /></span>-->
</label>
<label for="filterMSNcheckbox">
<input type="checkbox" name="filter[]" value="msn" <%= ((filteropts.contains("msn")) ? "checked" : "") %> id="filterMSNcheckbox">
<img src="images/msn.gif" alt="" border="0">
<span><fmt:message key="gateway.msn.shortservice" /></span>
<img src="images/msn.gif" alt="" border="0" alt="<fmt:message key="gateway.msn.shortservice" />">
<!--<span><fmt:message key="gateway.msn.shortservice" /></span>-->
</label>
<label for="filterSIPcheckbox">
<input type="checkbox" name="filter[]" value="sip" <%= ((filteropts.contains("sip")) ? "checked" : "") %> id="filterSIPcheckbox">
<img src="images/sipsimple.gif" alt="" border="0" alt="<fmt:message key="gateway.sip.shortservice" />">
<!--<span><fmt:message key="gateway.sip.shortservice" /></span>-->
</label>
<label for="filterYAHOOcheckbox">
<input type="checkbox" name="filter[]" value="yahoo" <%= ((filteropts.contains("yahoo")) ? "checked" : "") %> id="filterYAHOOcheckbox">
<img src="images/yahoo.gif" alt="" border="0">
<span><fmt:message key="gateway.yahoo.shortservice" /></span>
<img src="images/yahoo.gif" alt="" border="0" alt="<fmt:message key="gateway.yahoo.shortservice" />">
<!--<span><fmt:message key="gateway.yahoo.shortservice" /></span>-->
</label>
<label for="filterActiveOnly">
<input type="checkbox" name="filter[]" value="signedon" <%= ((filteropts.contains("signedon")) ? "checked" : "") %> id="filterActiveOnly">
......
......@@ -354,6 +354,7 @@
GatewaySettings icqSettings = new GatewaySettings(out, plugin, TransportType.icq, LocaleUtils.getLocalizedString("gateway.icq.service", "gateway"));
GatewaySettings ircSettings = new GatewaySettings(out, plugin, TransportType.irc, LocaleUtils.getLocalizedString("gateway.irc.service", "gateway"));
GatewaySettings msnSettings = new GatewaySettings(out, plugin, TransportType.msn, LocaleUtils.getLocalizedString("gateway.msn.service", "gateway"));
GatewaySettings sipSettings = new GatewaySettings(out, plugin, TransportType.sip, LocaleUtils.getLocalizedString("gateway.sip.service", "gateway"));
GatewaySettings yahooSettings = new GatewaySettings(out, plugin, TransportType.yahoo, LocaleUtils.getLocalizedString("gateway.yahoo.service", "gateway"));
%>
......@@ -615,6 +616,7 @@
<p><fmt:message key="gateway.web.settings.unstable.notice" /></p>
<% sipSettings.printSettingsDialog(); %>
<% yahooSettings.printSettingsDialog(); %>
</form>
......
......@@ -123,21 +123,3 @@ function toggleEdit(theNum) {
Effect.Appear($(editRow), {duration: .2});
}
}
/*
toggleFilters function
this is for a future feature, to replace the row of filter options with a
dynamic pulldown menu.
*/
/*
function toggleFilters() {
if ($(jiveFilterDrop).style.display != 'none') {
Effect.toggle($(jiveFilterDrop),'slide', {duration: .4});
} else {
Effect.toggle($(jiveFilterDrop),'slide', {duration: .4});
}
}
*/
\ No newline at end of file
......@@ -344,6 +344,14 @@ a.jive-gatewayButtonOn {
background: url(../images/msn-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-SIPon {
background: url(../images/sip.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-SIPoff {
background: url(../images/sip-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-YAHOOon {
background: url(../images/yahoo.gif) no-repeat left;
background-position: 0px 1px;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment