mirror of https://github.com/sipwise/jitsi.git
Restores OTR plugin version to 7f9f9ab73c from 2014-01-02
parent
9e546dd21c
commit
3189b4969c
Binary file not shown.
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.otr;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import org.osgi.framework.*;
|
||||
|
||||
/**
|
||||
* The OtrContactManager is used for accessing <tt>OtrContact</tt>s in a static
|
||||
* way.
|
||||
*
|
||||
* The <tt>OtrContact</tt> class is just a wrapper of [Contact, ContactResource]
|
||||
* pairs. Its purpose is for the otr plugin to be able to create different
|
||||
* <tt>Session</tt>s for every ContactResource that a Contact has.
|
||||
*
|
||||
* Currently, only the Jabber protocol supports ContactResources.
|
||||
*
|
||||
* @author Marin Dzhigarov
|
||||
*
|
||||
*/
|
||||
public class OtrContactManager implements ServiceListener
|
||||
{
|
||||
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger logger = Logger.getLogger(OtrContactManager.class);
|
||||
|
||||
/**
|
||||
* A map that caches OtrContacts to minimize memory usage.
|
||||
*/
|
||||
private static final Map<Contact, List<OtrContact>> contactsMap =
|
||||
new ConcurrentHashMap<Contact, List<OtrContact>>();
|
||||
|
||||
/**
|
||||
* The <tt>OtrContact</tt> class is just a wrapper of
|
||||
* [Contact, ContactResource] pairs. Its purpose is for the otr plugin to be
|
||||
* able to create different <tt>Session</tt>s for every ContactResource that
|
||||
* a Contact has.
|
||||
*
|
||||
* @author Marin Dzhigarov
|
||||
*
|
||||
*/
|
||||
public static class OtrContact
|
||||
{
|
||||
public final Contact contact;
|
||||
|
||||
public final ContactResource resource;
|
||||
|
||||
private OtrContact(Contact contact, ContactResource resource)
|
||||
{
|
||||
this.contact = contact;
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
|
||||
if (!(obj instanceof OtrContact))
|
||||
return false;
|
||||
|
||||
OtrContact other = (OtrContact) obj;
|
||||
|
||||
if (this.contact != null && this.contact.equals(other.contact))
|
||||
{
|
||||
if (this.resource != null && resource.equals(other.resource))
|
||||
return true;
|
||||
if (this.resource == null && other.resource == null)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int result = 17;
|
||||
|
||||
result = 31 * result + (contact == null ? 0 : contact.hashCode());
|
||||
result = 31 * result + (resource == null ? 0 : resource.hashCode());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <tt>OtrContact</tt> that represents this
|
||||
* [Contact, ContactResource] pair from the cache. If such pair does not
|
||||
* still exist it is then created and cached for further usage.
|
||||
*
|
||||
* @param contact the <tt>Contact</tt> that the returned OtrContact
|
||||
* represents.
|
||||
* @param resource the <tt>ContactResource</tt> that the returned OtrContact
|
||||
* represents.
|
||||
* @return The <tt>OtrContact</tt> that represents this
|
||||
* [Contact, ContactResource] pair.
|
||||
*/
|
||||
public static OtrContact getOtrContact(
|
||||
Contact contact, ContactResource resource)
|
||||
{
|
||||
if (contact == null)
|
||||
return null;
|
||||
|
||||
List<OtrContact> otrContactsList = contactsMap.get(contact);
|
||||
if (otrContactsList != null)
|
||||
{
|
||||
for (OtrContact otrContact : otrContactsList)
|
||||
{
|
||||
if (resource != null && resource.equals(otrContact.resource))
|
||||
return otrContact;
|
||||
}
|
||||
OtrContact otrContact = new OtrContact(contact, resource);
|
||||
synchronized (otrContactsList)
|
||||
{
|
||||
while (!otrContactsList.contains(otrContact))
|
||||
otrContactsList.add(otrContact);
|
||||
}
|
||||
return otrContact;
|
||||
}
|
||||
else
|
||||
{
|
||||
synchronized (contactsMap)
|
||||
{
|
||||
while (!contactsMap.containsKey(contact))
|
||||
{
|
||||
otrContactsList = new ArrayList<OtrContact>();
|
||||
contactsMap.put(contact, otrContactsList);
|
||||
}
|
||||
}
|
||||
return getOtrContact(contact, resource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up unused cached up Contacts.
|
||||
*/
|
||||
public void serviceChanged(ServiceEvent event)
|
||||
{
|
||||
Object service
|
||||
= OtrActivator.bundleContext.getService(event.getServiceReference());
|
||||
|
||||
if (!(service instanceof ProtocolProviderService))
|
||||
return;
|
||||
|
||||
if (event.getType() == ServiceEvent.UNREGISTERING)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(
|
||||
"Unregistering a ProtocolProviderService, cleaning"
|
||||
+ " OTR's Contact to OtrContact map");
|
||||
}
|
||||
|
||||
ProtocolProviderService provider
|
||||
= (ProtocolProviderService) service;
|
||||
|
||||
synchronized(contactsMap)
|
||||
{
|
||||
Iterator<Contact> i = contactsMap.keySet().iterator();
|
||||
|
||||
while (i.hasNext())
|
||||
{
|
||||
if (provider.equals(i.next().getProtocolProvider()))
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,438 +0,0 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.otr.authdialog;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.imageio.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.Timer;
|
||||
|
||||
import net.java.otr4j.session.*;
|
||||
import net.java.sip.communicator.plugin.desktoputil.*;
|
||||
import net.java.sip.communicator.plugin.otr.*;
|
||||
import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact;
|
||||
import net.java.sip.communicator.service.contactlist.*;
|
||||
import net.java.sip.communicator.service.gui.*;
|
||||
import net.java.sip.communicator.service.gui.Container;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* A special {@link JMenuBar} that controls the switching of OTRv3 outgoing
|
||||
* sessions in case the remote party is logged in multiple times.
|
||||
*
|
||||
* @author Marin Dzhigarov
|
||||
*
|
||||
*/
|
||||
public class OTRv3OutgoingSessionSwitcher
|
||||
extends SIPCommMenuBar
|
||||
implements PluginComponent,
|
||||
ActionListener,
|
||||
ScOtrEngineListener,
|
||||
ScOtrKeyManagerListener
|
||||
{
|
||||
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(OTRv3OutgoingSessionSwitcher.class);
|
||||
|
||||
private final PluginComponentFactory parentFactory;
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private final SelectorMenu menu = new SelectorMenu();
|
||||
|
||||
private ButtonGroup buttonGroup = new ButtonGroup();
|
||||
|
||||
private OtrContact contact;
|
||||
|
||||
/**
|
||||
* A map used for storing each <tt>Session</tt>s corresponding <tt>JMenuItem
|
||||
* </tt>.
|
||||
*/
|
||||
private final Map<Session, JMenuItem> outgoingSessions
|
||||
= new HashMap<Session, JMenuItem>();
|
||||
|
||||
/**
|
||||
* An animated {@link JMenu}
|
||||
* @author Marin Dzhigarov
|
||||
*
|
||||
*/
|
||||
private static class SelectorMenu
|
||||
extends SIPCommMenu
|
||||
{
|
||||
/**
|
||||
* Serial version UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
Image image = OtrActivator.resourceService.getImage(
|
||||
"service.gui.icons.DOWN_ARROW_ICON").getImage();
|
||||
|
||||
private static float alpha = 0.95f;
|
||||
|
||||
private final Timer alphaChanger = new Timer(20, new ActionListener() {
|
||||
|
||||
private float incrementer = -.03f;
|
||||
|
||||
private int fadeCycles = 0;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
float newAlpha = alpha + incrementer;
|
||||
if (newAlpha < 0.2f)
|
||||
{
|
||||
newAlpha = 0.2f;
|
||||
incrementer = -incrementer;
|
||||
} else if (newAlpha > 0.85f)
|
||||
{
|
||||
newAlpha = 0.85f;
|
||||
incrementer = -incrementer;
|
||||
fadeCycles++;
|
||||
}
|
||||
alpha = newAlpha;
|
||||
if (fadeCycles >= 3)
|
||||
{
|
||||
alphaChanger.stop();
|
||||
fadeCycles = 0;
|
||||
alpha = 1f;
|
||||
}
|
||||
SelectorMenu.this.repaint();
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g)
|
||||
{
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setComposite(
|
||||
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
|
||||
g.drawImage(image, getWidth() - image.getWidth(this) - 1,
|
||||
(getHeight() - image.getHeight(this) - 1) / 2, this);
|
||||
|
||||
super.paintComponent(g2d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fade in and out effect for this {@link JMenu}
|
||||
*/
|
||||
public void fadeAnimation()
|
||||
{
|
||||
alphaChanger.stop();
|
||||
alpha = 0.85f;
|
||||
SelectorMenu.this.repaint();
|
||||
alphaChanger.start();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The OTRv3OutgoingSessionSwitcher constructor
|
||||
*/
|
||||
public OTRv3OutgoingSessionSwitcher(Container container,
|
||||
PluginComponentFactory parentFactory)
|
||||
{
|
||||
this.parentFactory = parentFactory;
|
||||
|
||||
setPreferredSize(new Dimension(30, 28));
|
||||
setMaximumSize(new Dimension(30, 28));
|
||||
setMinimumSize(new Dimension(30, 28));
|
||||
|
||||
this.menu.setPreferredSize(new Dimension(30, 45));
|
||||
this.menu.setMaximumSize(new Dimension(30, 45));
|
||||
|
||||
this.add(menu);
|
||||
|
||||
this.setBorder(null);
|
||||
this.menu.setBorder(null);
|
||||
this.menu.setOpaque(false);
|
||||
this.setOpaque(false);
|
||||
this.menu.setVisible(false);
|
||||
|
||||
/*
|
||||
* XXX This OtrV3OutgoingSessionSwitcher instance cannot be added as a
|
||||
* listener to scOtrEngine and scOtrKeyManager without being removed
|
||||
* later on because the latter live forever. Unfortunately, the
|
||||
* dispose() method of this instance is never executed. OtrWeakListener
|
||||
* will keep this instance as a listener of scOtrEngine and
|
||||
* scOtrKeyManager for as long as this instance is necessary. And this
|
||||
* instance will be strongly referenced by the JMenuItems which depict
|
||||
* it. So when the JMenuItems are gone, this instance will become
|
||||
* obsolete and OtrWeakListener will remove it as a listener of
|
||||
* scOtrEngine and scOtrKeyManager.
|
||||
*/
|
||||
new OtrWeakListener<OTRv3OutgoingSessionSwitcher>(
|
||||
this,
|
||||
OtrActivator.scOtrEngine, OtrActivator.scOtrKeyManager);
|
||||
|
||||
try
|
||||
{
|
||||
finishedPadlockImage = new ImageIcon(ImageIO.read(
|
||||
OtrActivator.resourceService.getImageURL(
|
||||
"plugin.otr.FINISHED_ICON_BLACK_16x16")));
|
||||
verifiedLockedPadlockImage = new ImageIcon(ImageIO.read(
|
||||
OtrActivator.resourceService.getImageURL(
|
||||
"plugin.otr.ENCRYPTED_ICON_BLACK_16x16")));
|
||||
unverifiedLockedPadlockImage = new ImageIcon(ImageIO.read(
|
||||
OtrActivator.resourceService.getImageURL(
|
||||
"plugin.otr.ENCRYPTED_UNVERIFIED_ICON_BLACK_16x16")));
|
||||
unlockedPadlockImage = new ImageIcon(ImageIO.read(
|
||||
OtrActivator.resourceService.getImageURL(
|
||||
"plugin.otr.PLAINTEXT_ICON_16x16")));
|
||||
} catch (IOException e)
|
||||
{
|
||||
logger.debug("Failed to load padlock image");
|
||||
}
|
||||
|
||||
buildMenu(contact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPositionIndex()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current contact. Meant to be used by plugin components that
|
||||
* are interested of the current contact. The current contact is the contact
|
||||
* for the currently selected chat transport.
|
||||
*
|
||||
* @param contact the current contact
|
||||
*/
|
||||
public void setCurrentContact(Contact contact)
|
||||
{
|
||||
if (this.contact != null && this.contact.contact == contact)
|
||||
return;
|
||||
|
||||
this.contact =
|
||||
OtrContactManager.getOtrContact(contact, null);
|
||||
buildMenu(this.contact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current meta contact. Meant to be used by plugin components that
|
||||
* are interested of the current contact. The current contact could be the
|
||||
* contact currently selected in the contact list or the contact for the
|
||||
* currently selected chat, etc. It depends on the container, where this
|
||||
* component is meant to be added.
|
||||
*
|
||||
* @param metaContact the current meta contact
|
||||
*/
|
||||
public void setCurrentContact(MetaContact metaContact)
|
||||
{
|
||||
setCurrentContact((metaContact == null) ? null : metaContact
|
||||
.getDefaultContact());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current contact. Meant to be used by plugin components that
|
||||
* are interested of the current contact. The current contact is the contact
|
||||
* for the currently selected chat transport.
|
||||
*
|
||||
* @param contact the current contact
|
||||
* @param resourceName the <tt>ContactResource</tt> name. Some components
|
||||
* may be interested in a particular ContactResource of a contact.
|
||||
*/
|
||||
public void setCurrentContact(Contact contact, String resourceName)
|
||||
{
|
||||
if (this.contact != null && this.contact.contact == contact)
|
||||
return;
|
||||
|
||||
if (resourceName == null)
|
||||
{
|
||||
this.contact =
|
||||
OtrContactManager.getOtrContact(contact, null);
|
||||
buildMenu(this.contact);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ContactResource resource : contact.getResources())
|
||||
{
|
||||
if (resource.getResourceName().equals(resourceName))
|
||||
{
|
||||
OtrContact otrContact =
|
||||
OtrContactManager.getOtrContact(contact, resource);
|
||||
if (this.contact == otrContact)
|
||||
return;
|
||||
this.contact = otrContact;
|
||||
buildMenu(this.contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentContactGroup(MetaContactGroup metaGroup) {}
|
||||
|
||||
@Override
|
||||
public void setCurrentAccountID(AccountID accountID) {}
|
||||
|
||||
@Override
|
||||
public PluginComponentFactory getParentFactory()
|
||||
{
|
||||
return parentFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ScOtrKeyManagerListener#contactVerificationStatusChanged(
|
||||
* Contact).
|
||||
*/
|
||||
public void contactVerificationStatusChanged(OtrContact contact)
|
||||
{
|
||||
buildMenu(contact);
|
||||
if (this.menu.isVisible())
|
||||
this.menu.fadeAnimation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ScOtrEngineListener#contactPolicyChanged(Contact).
|
||||
*/
|
||||
public void contactPolicyChanged(Contact contact) {}
|
||||
|
||||
/**
|
||||
* Implements ScOtrKeyManagerListener#globalPolicyChanged().
|
||||
*/
|
||||
public void globalPolicyChanged() {}
|
||||
|
||||
/**
|
||||
* Implements ScOtrEngineListener#sessionStatusChanged(OtrContact).
|
||||
*/
|
||||
public void sessionStatusChanged(OtrContact contact)
|
||||
{
|
||||
buildMenu(contact);
|
||||
if (this.menu.isVisible())
|
||||
this.menu.fadeAnimation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ScOtrEngineListener#multipleInstancesDetected(OtrContact).
|
||||
*/
|
||||
public void multipleInstancesDetected(OtrContact contact)
|
||||
{
|
||||
buildMenu(contact);
|
||||
if (this.menu.isVisible())
|
||||
this.menu.fadeAnimation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ScOtrEngineListener#outgoingSessionChanged(OtrContact).
|
||||
*/
|
||||
public void outgoingSessionChanged(OtrContact contact)
|
||||
{
|
||||
buildMenu(contact);
|
||||
}
|
||||
|
||||
private ImageIcon verifiedLockedPadlockImage;
|
||||
|
||||
private ImageIcon unverifiedLockedPadlockImage;
|
||||
|
||||
private ImageIcon finishedPadlockImage;
|
||||
|
||||
private ImageIcon unlockedPadlockImage;
|
||||
|
||||
/**
|
||||
* Builds the JMenu used for switching between outgoing OTRv3 Sessions in
|
||||
* case the remote party is logged in multiple locations
|
||||
*
|
||||
* @param otrContact the contact which is logged in multiple locations
|
||||
*/
|
||||
private void buildMenu(OtrContact otrContact)
|
||||
{
|
||||
if (otrContact == null || !this.contact.equals(otrContact))
|
||||
{
|
||||
return;
|
||||
}
|
||||
menu.removeAll();
|
||||
java.util.List<Session> multipleInstances =
|
||||
OtrActivator.scOtrEngine.getSessionInstances(
|
||||
otrContact);
|
||||
|
||||
Session outgoingSession =
|
||||
OtrActivator.scOtrEngine.getOutgoingSession(otrContact);
|
||||
int index = 0;
|
||||
for (Session session : multipleInstances)
|
||||
{
|
||||
index++;
|
||||
if (!outgoingSessions.containsKey(session))
|
||||
{
|
||||
JMenuItem menuItem = new JRadioButtonMenuItem();
|
||||
outgoingSessions.put(session, menuItem);
|
||||
menuItem.addActionListener(this);
|
||||
}
|
||||
|
||||
JMenuItem menuItem = outgoingSessions.get(session);
|
||||
menuItem.setText("Session " + index);
|
||||
|
||||
ImageIcon imageIcon = null;
|
||||
switch (session.getSessionStatus(session.getReceiverInstanceTag()))
|
||||
{
|
||||
case ENCRYPTED:
|
||||
PublicKey pubKey =
|
||||
session.getRemotePublicKey(session.getReceiverInstanceTag());
|
||||
String fingerprint =
|
||||
OtrActivator.scOtrKeyManager.
|
||||
getFingerprintFromPublicKey(pubKey);
|
||||
imageIcon
|
||||
= OtrActivator.scOtrKeyManager.isVerified(
|
||||
otrContact.contact, fingerprint)
|
||||
? verifiedLockedPadlockImage
|
||||
: unverifiedLockedPadlockImage;
|
||||
break;
|
||||
case FINISHED:
|
||||
imageIcon = finishedPadlockImage;
|
||||
break;
|
||||
case PLAINTEXT:
|
||||
imageIcon = unlockedPadlockImage;
|
||||
break;
|
||||
}
|
||||
menuItem.setIcon(imageIcon);
|
||||
|
||||
menu.add(menuItem);
|
||||
SelectedObject selectedObject =
|
||||
new SelectedObject(imageIcon, session);
|
||||
|
||||
buttonGroup.add(menuItem);
|
||||
menuItem.repaint();
|
||||
if (session == outgoingSession)
|
||||
{
|
||||
this.menu.setSelected(selectedObject);
|
||||
setSelected(menu.getItem(index - 1));
|
||||
}
|
||||
|
||||
}
|
||||
updateEnableStatus();
|
||||
menu.repaint();
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
for (Map.Entry<Session, JMenuItem> entry : outgoingSessions.entrySet())
|
||||
{
|
||||
JMenuItem menuItem = (JRadioButtonMenuItem) e.getSource();
|
||||
if (menuItem.equals(entry.getValue()))
|
||||
{
|
||||
OtrActivator.scOtrEngine.setOutgoingSession(
|
||||
contact, entry.getKey().getReceiverInstanceTag());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the menu visibility. The menu is visible as soon as it
|
||||
* contains two or more items. If it is empty, it is invisible.
|
||||
*/
|
||||
private void updateEnableStatus()
|
||||
{
|
||||
this.menu.setVisible(this.menu.getItemCount() > 1);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue